/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MyPhotoIndex.DataAccess;
using MyPhotoIndex.Importer;
using MyPhotoIndex.Controls;
using System.IO;
using MyPhotoIndex.ImageBank.Query;
using MyPhotoIndex.ImageBank;
using System.Collections.ObjectModel;
using MyPhotoIndex.Wizards.Import;
using MyPhotoIndex.Wizards.CameraImport;
using MyPhotoIndex.Controls.TagTree;
using MyPhotoIndex.MainMDI;
using MyPhotoIndex.Utilities;
using MyPhotoIndex.Plugins;
using MyPhotoIndex.Settings;
using System.Diagnostics;
using MyPhotoIndex.Interfaces;
using System.Drawing.Printing;
using MyPhotoIndex.Plugins.ImageFormatProviders;
using System.Drawing.Drawing2D;
using System.Threading;
using MyPhotoIndex.VersionCheck;
using System.Security.Permissions;
using System.Reflection;
using System.Globalization;
using MyPhotoIndex.Interfaces.ImageFormatProviders;
using MyPhotoIndex.Interfaces.Plugins;
using MyPhotoIndex.Interfaces.Tagging;
using MyPhotoIndex.Interfaces.Imaging;
using MyPhotoIndex.Plugins.DataProviders;
using System.Collections;
using System.Xml;

namespace MyPhotoIndex
{
    public partial class Main : Form
    {
        internal delegate void FormProgressUpdateDelegate(int maxValue, int value);
        internal delegate void FormProgressShowDelegate(bool show, ProgressBarStyle style);
        internal delegate void FormVoidObjectDelegte(Object state);

        private int m_lastImageSize;
        private IVideoPlayer m_currentVideoPlayer;
        private SelectedImageCollection m_selectedImages;
        private FileDragDrop m_fileDragDrop;
        private AsyncProgressForm m_progressForm;
        private ToolTip m_toolTip = new ToolTip();
        private ImageList m_categoriesImageList = new ImageList();

        public Main()
        {
            InitializeComponent();

            ImageCountLabel.Text = String.Empty;

            Edit_Delete_MenuItem.Enabled = false;
            saveAsToolStripMenuItem.Enabled = false;

            ExportImagesAndTagsMenuItem.Click += new EventHandler(ExportImagesAndTagsMenuItem_Click);
            ImportImagesAndTags.Click += new EventHandler(ImportImagesAndTags_Click);

            Storage.Instance.FilterChangedEvent += new EventHandler(Instance_FilterChangedEvent);
            Storage.Instance.ImageCollectionLoadedEvent += new EventHandler<EventArgs>(Instance_ImageCollectionLoadedEvent);
            Storage.Instance.ImageCollectionLoadingEvent += new EventHandler<EventArgs>(Instance_ImageCollectionLoadingEvent);
            photoThumbViewer1.ImageList = Storage.Instance;

            photoThumbViewer1.ThumbnailDragDropEvent += new EventHandler<ThumbnailDragDropEventArgs>(photoThumbViewer1_ThumbnailDragDropEvent);
            photoThumbViewer1.ThumbnailDragOverEvent += new EventHandler<ThumbnailDragDropEventArgs>(photoThumbViewer1_ThumbnailDragOverEvent);
            photoThumbViewer1.ThumbnailDragEnterEvent += new EventHandler<DragEventArgs>(photoThumbViewer1_ThumbnailDragEnterEvent);
            photoThumbViewer1.ThumbnailDragLeaveEvent += new EventHandler<EventArgs>(photoThumbViewer1_ThumbnailDragLeaveEvent);
            photoThumbViewer1.ThumbnailIconMouseEnterEvent += new EventHandler<ThumbnailMouseEventArgs>(photoThumbViewer1_ThumbnailIconMouseEnterEvent);
            photoThumbViewer1.ThumbnailIconMouseLeaveEvent += new EventHandler<ThumbnailMouseEventArgs>(photoThumbViewer1_ThumbnailIconMouseLeaveEvent);
            photoThumbViewer1.ThumbnailMouseClickEvent += new EventHandler<ThumbnailMouseEventArgs>(photoThumbViewer1_ThumbnailMouseClickEvent);
            photoThumbViewer1.ThumbnailMouseDoubleClickEvent += new EventHandler<ThumbnailMouseEventArgs>(photoThumbViewer1_ThumbnailMouseDoubleClickEvent);
            photoThumbViewer1.SelectionChangedEvent += new EventHandler<SelectedImageInfo>(photoThumbViewer1_SelectionChangedEvent);
            photoThumbViewer1.KeyPress += new KeyPressEventHandler(photoThumbViewer1_KeyPress);
            photoThumbViewer1.CategoryRenderer = new MPICategoryRenderer(m_categoriesImageList);

            m_selectedImages = new SelectedImageCollection(Storage.Instance);
            SelectedThumbnailViewer.ImageList = m_selectedImages;
            SelectedThumbnailViewer.ThumbnailMouseClickEvent += new EventHandler<ThumbnailMouseEventArgs>(SelectedThumbnailViewerContextMenu_ThumbnailMouseClickEvent);
            SelectedThumbnailViewer.ThumbnailMouseDoubleClickEvent += new EventHandler<ThumbnailMouseEventArgs>(SelectedThumbnailViewer_ThumbnailMouseDoubleClickEvent);
            SelectedThumbnailViewer.DragEnter += new DragEventHandler(SelectedThumbnailViewer_DragEnter);
            SelectedThumbnailViewer.DragDrop += new DragEventHandler(SelectedThumbnailViewer_DragDrop);
            SelectedThumbnailViewer.DragOver += new DragEventHandler(SelectedThumbnailViewer_DragOver);
            SelectedThumbnailViewer.DragLeave += new EventHandler(SelectedThumbnailViewer_DragLeave);

            myPhotoIndexImageTagTreeView1.AfterCheck += new TreeViewEventHandler(myPhotoIndexImageTagTreeView1_AfterCheck);
            myPhotoIndexImageTagTreeView1.DragEnter += new DragEventHandler(myPhotoIndexImageTagTreeView1_DragEnter);
            myPhotoIndexImageTagTreeView1.DragLeave += new EventHandler(myPhotoIndexImageTagTreeView1_DragLeave);
            myPhotoIndexImageTagTreeView1.DragOver += new DragEventHandler(myPhotoIndexImageTagTreeView1_DragOver);
            myPhotoIndexImageTagTreeView1.DragDrop += new DragEventHandler(myPhotoIndexImageTagTreeView1_DragDrop);

            TagsViewToolStripMenuItem.Click += new EventHandler(TagsViewToolStripMenuItem_Click);
            FolderViewToolStripMenuItem.Click += new EventHandler(FolderViewToolStripMenuItem_Click);

            SortToolStripComboBox.Size = new Size(150, 21);
            SortToolStripComboBox.SelectedIndexChanged += new EventHandler(SortToolStripComboBox_SelectedIndexChanged);

            sortOrderToolStripButton.CheckedChanged += new EventHandler(sortOrderToolStripButton_CheckedChanged);

            photo_Rotate_LeftMenuItem.Click += new EventHandler(rcmenuRotateLeft90_Click);
            photo_Rotate_RightMenuItem.Click += new EventHandler(rcmenuRotateRight90_Click);
            photo_ShareMenuItem.Click += new EventHandler(shareToolStripMenuItem_Click);

            AdjustSelectedImagesPane();

            clearTagsPaletteToolStripButton.Click += new EventHandler(clearTagsPaletteToolStripButton_Click);
            tagsPaletteThumbnailViewer.ThumbnailMouseClickEvent += new EventHandler<ThumbnailMouseEventArgs>(tagsPaletteThumbnailViewer_ThumbnailMouseClickEvent);

            treeView1.MouseClick += new MouseEventHandler(treeView1_MouseClick);

            LastMonth.Click += new EventHandler(LastMonth_Click);
            LastWeek.Click += new EventHandler(LastWeek_Click);

            shareToolStripButton.ButtonClick += new EventHandler(shareToolStripButton_Click);

            //tag tree
            cmAddTag.Click += new EventHandler(cmAddTag_Click);
            cmRemoveTag.Click += new EventHandler(cmRemoveTag_Click);
            cmProperties.Click += new EventHandler(cmProperties_Click);
            sortAlphaToolStripMenuItem.Click += new EventHandler(sortAlphaToolStripMenuItem_Click);
            SortByTagDatetoolStripMenuItem.Click += new EventHandler(SortByTagDatetoolStripMenuItem_Click);
            assignToSelectedImagesToolStripMenuItem.Click += new EventHandler(assignToSelectedImagesToolStripMenuItem_Click);

            ImageTagCollection.Instance.ImageTagCollectionLoaded += new EventHandler(Instance_ImageTagCollectionLoaded);
            ImageCategoryCollection.Instance.ImageCategoryCollectionLoadedEvent += new EventHandler<EventArgs>(Instance_ImageCategoryCollectionLoadedEvent);

            editCategoriesToolStripMenuItem.Click += new EventHandler(editCategoriesToolStripMenuItem_Click);

            toolStripSearchBox.InnerControl.KeyUp += new KeyEventHandler(InnerControl_KeyUp);
            CreateSortCombo();

            m_fileDragDrop = new FileDragDrop(this);
            m_fileDragDrop.FileDroppedEvent += new EventHandler<FileDropEventArgs>(m_fileDragDrop_FileDroppedEvent);

            LoadCategoriesImageList();

            myPhotoIndexSplitContainer1.Panel1Collapsed = true;
            myPhotoIndexSplitContainer1.SplitterDistance = 28;
            addTabToolStripButton.Click += new EventHandler(addTabToolStripButton_Click);

            importExportToolStripMenuItem.Visible = false;

            //ContextMenu
            this.DecryptToolStripMenuItem.Click += new System.EventHandler(this.DecryptToolStripMenuItem_Click);
            this.updateSourceLabelToolStripMenuItem.Click += new EventHandler(updateSourceLabelToolStripMenuItem_Click);
            this.ImageVersionsShowAllToolStripMenuItem.Click += new EventHandler(ImageVersionsShowAllToolStripMenuItem_Click);
            this.imageVersionsSetAsPrimaryToolStripMenuItem.Click += new EventHandler(imageVersionsSetAsPrimaryToolStripMenuItem_Click);
            this.breakVersionSetToolStripMenuItem.Click += new EventHandler(breakVersionSetToolStripMenuItem_Click);
            this.createVersionSetToolStripMenuItem.Click += new EventHandler(createVersionSetToolStripMenuItem_Click);
            this.moveToFolderToolStripMenuItem.Click += new EventHandler(moveToFolderToolStripMenuItem_Click);
            this.SetAsWpToolStripMenuItem.Click += new EventHandler(SetAsWpToolStripMenuItem_Click);

            //main menu
            //edit menu
            invertSelectionToolStripMenuItem.Click += new EventHandler(invertSelectionToolStripMenuItem_Click);

            //Image menu
            advancedQueryToolStripMenuItem.Click += new EventHandler(advancedQueryToolStripMenuItem_Click);
            SavedQueryRemoveToolStripMenuItem.Click += new EventHandler(SavedQueryRemoveToolStripMenuItem_Click);
            savedQueryEditToolStripMenuItem.Click += new EventHandler(savedQueryEditToolStripMenuItem_Click);
            ClearCachedPasswordsToolStripMenuItem.Click += new EventHandler(ClearCachedPasswordsToolStripMenuItem_Click);

            //help menu
            checkForUpdatesToolStripMenuItem.Click += new EventHandler(checkForUpdatesToolStripMenuItem_Click);

            //Set Global strings
            ApplicationAlert.YesStr = Resources.Resources.Str_Yes;
            ApplicationAlert.NoStr = Resources.Resources.Str_No;

            //language menu
            lithuanianToolStripMenuItem.Click += new EventHandler(lithuanianToolStripMenuItem_Click);

            //register global keyboard shortcuts
            RegisterKeyboardShortcuts();
            RegisterThumbnailInfoTextContextMenuEvents();

            if (ApplicationFolders.IsAppPortable == true)
            {
                UpdatePoratableAppVisuals();
            }
        }

        private void UpdatePoratableAppVisuals()
        {
            //open photo index -- use only one default index
            toolStripMenuItem1.Enabled = false;
        }

        private void RegisterKeyboardShortcuts()
        {
            ApplicationSettings.Default.KeyboardMappings.RegisterKeyBoardEvent("{A03BFD6F-869F-4719-B225-7F6BF30CB5F1}", new KeyboardShortcutOperationDelegate(AssignSelectedTagsToImages));
            assignToSelectedImagesToolStripMenuItem.ShortcutKeys = Keys.Control | Keys.F2;
        }

        void InnerControl_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                toolStripSearchButton.PerformClick();
            }
        }

        void ImportImagesAndTags_Click(object sender, EventArgs e)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        void ExportImagesAndTagsMenuItem_Click(object sender, EventArgs e)
        {
            using (XmlWriter writer = new XmlTextWriter(@"c:\id.xml", Encoding.Unicode))
            {
                List<IImageData> images = new List<IImageData>();
                for (int i = 0; i < photoThumbViewer1.SelectedImages.Count; i++)
                {
                    IImageData imageData = photoThumbViewer1.ImageList[photoThumbViewer1.SelectedImages[i]];
                    images.Add(imageData);
                }

                ImageMetadataExporter imageDataExporter = new ImageMetadataExporter(images.AsReadOnly(), DataAccessProvider.Instance.GetDbIndexId());
                imageDataExporter.Export(writer, true);
            }
        }

        void addTabToolStripButton_Click(object sender, EventArgs e)
        {
            ToolStripButton newTab = new ToolStripButton("new tab");
            newTab.Width = 200;
            newTab.Select();

            tabsToolStrip.Items.Insert(tabsToolStrip.Items.Count - 1, newTab);
        }

        void editCategoriesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditImageCategoriesForm eicf = new EditImageCategoriesForm(m_categoriesImageList, ImageCategoryCollection.Instance);
            eicf.ShowDialog(this);

            BuildImageCategoriesMenu();
        }

        private void LoadCategoriesImageList()
        {
            m_categoriesImageList.ColorDepth = ColorDepth.Depth32Bit;
            m_categoriesImageList.Images.AddRange(new Image[]{
                                Properties.Resources.Category01,Properties.Resources.Category02,
                                Properties.Resources.Category03,Properties.Resources.Category04,
                                Properties.Resources.Category05,Properties.Resources.Category06,
                                Properties.Resources.Category07,Properties.Resources.Category08,
                                Properties.Resources.Category09,Properties.Resources.Category10,
                                Properties.Resources.Category11,Properties.Resources.Category12,
                                Properties.Resources.Category13,Properties.Resources.Category14,
                                Properties.Resources.Category15,Properties.Resources.Category16,
                                Properties.Resources.Category17,Properties.Resources.Category18,
                                Properties.Resources.Category19,Properties.Resources.Category20});
        }

        void shareToolStripButton_Click(object sender, EventArgs e)
        {
            ISharePlugin mailer = (ISharePlugin)Manager.GetPlugin("MyPhotoIndex.Plugins.WebCommunity.CommunityMailerPlugin");
            if (mailer == null)
            {
                return;
            }

            Share(mailer);
        }

        void imageSharingToolStripItem_Click(object sender, EventArgs e)
        {
            ISharePlugin mailer = (ISharePlugin)((ToolStripItem)sender).Tag;
            if (mailer == null)
            {
                return;
            }

            Share(mailer);
        }

        private void Share(ISharePlugin mailer)
        {
            if (ApplicationSettings.Default.ShowShareSettingsForm)
            {
                SharePreferences sp = new SharePreferences();
                if (sp.ShowDialog() == DialogResult.Cancel)
                {
                    return;
                }
            }

            Size imageSize = ApplicationSettings.Default.DefaultMailImageSize;

            List<IImageData> fileList = new List<IImageData>();

            foreach (int imageId in photoThumbViewer1.SelectedImages)
            {
                IImageData imageData = Storage.Instance[imageId];
                if (ValidateEncryptedImage(imageData) == true &&
                    imageData.IsVideo == false)
                {
                    fileList.Add(imageData);
                }
            }

            if (fileList.Count == 0)
            {
                // TODO: Give message.
                return;
            }

            mailer.Send(fileList.AsReadOnly(), imageSize);
        }

        private void BuildSharingPluginMenu()
        {
            if (shareToolStripButton.DropDownItems.Count > 0)
            {
                return;
            }

            String defaultMailPlugin = ApplicationSettings.Default.DefaultMailPlugin;

            ReadOnlyCollection<ISharePlugin> plugins = Manager.GetPlugins<ISharePlugin>();
            foreach (ISharePlugin plugin in plugins)
            {
                ToolStripItem newItem = shareToolStripButton.DropDownItems.Add(plugin.ToString());
                newItem.Tag = plugin;

                Image pluginIcon = null;
                try
                {
                    pluginIcon = plugin.Icon;
                }
                catch { }

                if (pluginIcon != null)
                {
                    newItem.Image = pluginIcon;
                    newItem.ImageScaling = ToolStripItemImageScaling.None;
                }

                newItem.Click += new EventHandler(imageSharingToolStripItem_Click);
            }
        }

        void SelectedThumbnailViewer_ThumbnailMouseDoubleClickEvent(object sender, ThumbnailMouseEventArgs e)
        {
            photoThumbViewer1.ClearSelection();
            photoThumbViewer1.SelectImage(e.ImageId, true);
            photoThumbViewer1.ScrollToSelected();
        }

        void tagsPaletteThumbnailViewer_ThumbnailMouseClickEvent(object sender, ThumbnailMouseEventArgs e)
        {
            if (e.MouseButton == MouseButtons.Right)
            {
                SelectedImagesContextMenu.Tag = tagsPaletteThumbnailViewer;
                SelectedImagesContextMenu.Show(tagsPaletteThumbnailViewer, e.X, e.Y);
            }
        }

        void clearTagsPaletteToolStripButton_Click(object sender, EventArgs e)
        {
            ClearTagsPalette();
        }

        void invertSelectionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            photoThumbViewer1.InvertSelection();
        }

        void m_fileDragDrop_FileDroppedEvent(object sender, FileDropEventArgs e)
        {
            this.Invoke(new FormVoidObjectDelegte(ImportDroppedFiles), new Object[] { e.Files });
        }

        void ImportDroppedFiles(Object state)
        {
            Cursor.Current = Cursors.WaitCursor;

            String[] files = state as String[];
            List<String> imaportFilesList = new List<string>();
            foreach (String file in files)
            {
                try
                {
                    if (String.IsNullOrEmpty(Path.GetExtension(file)) == true)
                    {
                        FilesSearch fs = new FilesSearch();
                        fs.SearchPattern = ImageFormatProviders.Default.ImporterFilterFormat;
                        fs.SearchSubfolders = true;
                        fs.SearchLocations.Add(file);

                        fs.Search();
                        imaportFilesList.AddRange(fs.FileList);
                    }
                    else
                    {
                        imaportFilesList.Add(file);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Log(file, ex);
                }
            }

            String importBatch = Guid.NewGuid().ToString();
            Importer.FileImageDataImporter importer = new FileImageDataImporter(importBatch);
            importer.UseCentralStorage = ApplicationFolders.UseCentralStorage;
            importer.CentralStoragePath = ApplicationFolders.CentralStorageLocation;

            importer.ImageDataImporterProcessEvent += new EventHandler<ImageDataImporterEventArgs>(importer_ImageDataImporterProcessEvent);

            try
            {
                using (m_progressForm = new AsyncProgressForm(this, Resources.Resources.ImportingImages, null, imaportFilesList.Count))
                {
                    importer.ImportFromFileList(imaportFilesList.ToArray(), ApplicationSettings.Default.CachedThumbnailSize);

                    m_progressForm.MakeInifinte();

                    ImageTagCollection.Instance.Load((ITagsDataAccessProvider)DataAccessProvider.Instance);
                    Storage.Instance.LoadImageList();
                    QueryParameter[] queryParameters = new QueryParameter[] { new ImageBatchQueryParameter(importBatch) };
                    myPhotoIndexImageTagTreeView1.UncheckAll();
                    Storage.Instance.Filter(queryParameters);
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }

            Cursor.Current = Cursors.Default;
        }

        void importer_ImageDataImporterProcessEvent(object sender, ImageDataImporterEventArgs e)
        {
            e.Stop = m_progressForm.Stop;
            m_progressForm.Increment(e.CurrentFile, e.Thumbnail);
        }

        void photoThumbViewer1_SelectionChangedEvent(object sender, SelectedImageInfo e)
        {
            UpdateMenuItemsStatus();
            PluginsHandler.InvokeSelectionChanged(photoThumbViewer1.SelectedImages, e);

            if (stickySelectionModeToolStripMenuItem.Checked &&
                e != SelectedImageInfo.Empty &&
                e.SelectionState == SelectedImageSelectedState.Select)
            {
                if (SelectedThumbnailViewer.IsSelected(e.ImageId) == false)
                {
                    // add images to the selected pane
                    m_selectedImages.Add(e.ImageId);
                    AdjustSelectedImagesPane();
                }
            }
        }

        private void UpdateMenuItemsStatus()
        {
            int selectedCount = photoThumbViewer1.SelectedImages.Count;

            Edit_Delete_MenuItem.Enabled = (selectedCount > 0);
            saveAsToolStripMenuItem.Enabled = (selectedCount > 0);
            photo_ShareMenuItem.Enabled = (selectedCount > 0);
            shareToolStripButton.Enabled = (selectedCount > 0);
            assignToSelectedImagesToolStripMenuItem.Enabled = (selectedCount > 0);

            bool canProtect = false;
            bool canDecrypt = false;
            bool canEncrypt = false;
            bool canUnlock = false;
            bool canRotate = false;
            bool canCreateVersionSet = false;
            bool canBreakVersionSet = false;

            int numOfPrimaryVersionSetImages = 0;

            foreach (int imageId in this.photoThumbViewer1.SelectedImages)
            {
                IImageData imageData = Storage.Instance[imageId];
                if (imageData == null)
                {
                    continue;
                }

                if (canRotate == false &&
                    imageData.CanRotate == true)
                {
                    canRotate = true;
                }

                if (canProtect == false &&
                    (imageData.FormatProvider.CanSave == true ||
                     imageData.Encrypted == true))
                {
                    canProtect = true;
                }

                if (canProtect == true &&
                    imageData.Encrypted == true)
                {
                    canDecrypt = true;
                    if (canUnlock == false)
                    {
                        IEncryptedFormatProvider provider = imageData.FormatProvider as IEncryptedFormatProvider;
                        if (provider != null)
                        {
                            canUnlock = !provider.IsCached(imageData.FileName);
                        }
                    }
                }
                else
                    if (canProtect == true)
                    {
                        canEncrypt = true;
                    }


                if (imageData.VersionParentId > -1 ||
                    imageData.VersionsCount > 0)
                {
                    canBreakVersionSet = true;
                }

                if (imageData.VersionParentId < 0)
                {
                    canCreateVersionSet = true;
                }

                if (imageData.VersionsCount > 0)
                {
                    numOfPrimaryVersionSetImages++;
                }

                if (canRotate == true &&
                    canProtect == true &&
                    canDecrypt == true &&
                    canUnlock == true &&
                    canEncrypt == true &&
                    canCreateVersionSet == true &&
                    canBreakVersionSet == true)
                {
                    break;
                }
            }

            PrivacyToolStripMenuItem.Enabled = canProtect;
            EncryptToolStripMenuItem.Enabled = canEncrypt;
            DecryptToolStripMenuItem.Enabled = canDecrypt;
            UnLockToolStripMenuItem.Enabled = canUnlock;

            rcmenuRotateLeft90.Enabled = canRotate;
            rcmenuRotateRight90.Enabled = canRotate;

            photo_Rotate_LeftMenuItem.Enabled = canRotate;
            photo_Rotate_RightMenuItem.Enabled = canRotate;

            createVersionSetToolStripMenuItem.Enabled = (canCreateVersionSet && (numOfPrimaryVersionSetImages <= 1) && selectedCount > 1);
            breakVersionSetToolStripMenuItem.Enabled = canBreakVersionSet;

            //one image only operations

            ImageVersionsShowAllToolStripMenuItem.Enabled = false;
            imageVersionsSetAsPrimaryToolStripMenuItem.Enabled = false;
            if (selectedCount == 1)
            {
                int imageId = this.photoThumbViewer1.SelectedImages[0];
                IImageData imageData = Storage.Instance[imageId];
                if (imageData != null)
                {
                    ImageVersionsShowAllToolStripMenuItem.Enabled = (imageData.VersionsCount > 0);
                    imageVersionsSetAsPrimaryToolStripMenuItem.Enabled = (imageData.VersionParentId > -1);
                }
            }

            ImageVersionsToolStripMenuItem.Enabled = (createVersionSetToolStripMenuItem.Enabled || breakVersionSetToolStripMenuItem.Enabled ||
                ImageVersionsShowAllToolStripMenuItem.Enabled || imageVersionsSetAsPrimaryToolStripMenuItem.Enabled);


            UpdateStatusBar();
        }

        void SortToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            Storage.Instance.SortingComparer = SortToolStripComboBox.SelectedItem as IImageSortComparer;
            Storage.Instance.SortAscending = (sortOrderToolStripButton.Checked == true);
            Storage.Instance.Sort();
            photoThumbViewer1.Refresh();
        }

        void sortOrderToolStripButton_CheckedChanged(object sender, EventArgs e)
        {
            sortOrderToolStripButton.Image =
                sortOrderToolStripButton.Checked ?
                    Properties.Resources.sort_ascending :
                        Properties.Resources.sort_descending;

            SortToolStripComboBox_SelectedIndexChanged(sender, e);
        }

        private void CreateSortCombo()
        {
            SortToolStripComboBox.Items.Add(new DateTakenImageListSorter());
            SortToolStripComboBox.Items.Add(new DateImportedImageListSorter());
            SortToolStripComboBox.Items.Add(new RatingImageListSorter());
            SortToolStripComboBox.Items.Add(new CategoryImageListSorter());
            SortToolStripComboBox.Items.Add(new FileNameImageListSorter());

            sortOrderToolStripButton.Checked = ApplicationSettings.Default.SortDescending;

            String lastSort = ApplicationSettings.Default.LastImageSorting;
            if (String.IsNullOrEmpty(lastSort) == false)
            {
                foreach (Object item in SortToolStripComboBox.Items)
                {
                    if (String.Compare(item.GetType().FullName, lastSort) == 0)
                    {
                        SortToolStripComboBox.SelectedItem = item;
                        break;
                    }
                }
            }
            else
            {
                SortToolStripComboBox.SelectedIndex = 0;
            }

            if (SortToolStripComboBox.SelectedItem == null)
            {
                SortToolStripComboBox.SelectedIndex = 0;
            }
        }

        private void Main_Load(object sender, EventArgs e)
        {
            //   ShowQueryPane(false);
            LoadPreferences();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            m_fileDragDrop.Dispose();
            SavePreferences();
            base.OnClosing(e);
        }

        private void LoadPreferences()
        {
            UpdateLanguageMenus();

            Version savedVersion = new Version(ApplicationSettings.Default.ConfigVersion);
            if (savedVersion < new Version("1.19.2990"))
            {
                splitContainer1.SplitterDistance = 255;

            }
            else
            {
                float split1width = (float)ApplicationSettings.Default.Splitter1Distance;
                splitContainer1.SplitterDistance = (int)split1width;
            }

            float delta = (float)Screen.PrimaryScreen.WorkingArea.Height - (float)ApplicationSettings.Default.SavedScreenHeightResolution;
            float split2height = (float)ApplicationSettings.Default.Splitter2Distance + delta;
            splitContainer2.SplitterDistance = (int)split2height;

            delta = (float)Screen.PrimaryScreen.WorkingArea.Height - (float)ApplicationSettings.Default.SavedScreenHeightResolution;
            float split3height = (float)ApplicationSettings.Default.Splitter3Distance + delta;
            splitContainer3.SplitterDistance = (int)split3height;

            m_lastImageSize = ApplicationSettings.Default.Thumbnailsize;
            MyPhotoIndexTrackBar1.Value = m_lastImageSize;

            ToggleFilterTree((ApplicationSettings.Default.LastFilterTreeView == 0) ? false : true);

            Storage.Instance.ThumbnailSize = ApplicationSettings.Default.CachedThumbnailSize;
            ApplicationFolders.CachePath = ApplicationSettings.Default.ImageCachePath;
            Storage.Instance.UpdateMediaMetaDataOnMediaChange = ApplicationSettings.Default.UpdateImageMetadataOnChange;

            ApplicationSettings.Default.WebProxySettings.RefreshProxySettings();
            ApplicationSettings.Default.SettingsSaved += new EventHandler(Default_SettingsSaved);

            photoThumbViewer1.ThumbnailTextInfoDisplayType = ApplicationSettings.Default.ThumbnailTextInfoDisplayType;
        }

        void Default_SettingsSaved(object sender, EventArgs e)
        {
            Storage.Instance.ThumbnailSize = ApplicationSettings.Default.CachedThumbnailSize;
            Storage.Instance.UpdateMediaMetaDataOnMediaChange = ApplicationSettings.Default.UpdateImageMetadataOnChange;

            try
            {
                Thread.CurrentThread.CurrentUICulture.DateTimeFormat.ShortDatePattern = ApplicationSettings.Default.DisplayDateFormat;
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
        }

        private void SavePreferences()
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            AssemblyName asmName = asm.GetName();
            String versionString = String.Format("{0}.{1}.{2}", asmName.Version.Major, asmName.Version.Minor, asmName.Version.Build);
            ApplicationSettings.Default.ConfigVersion = versionString;

            ApplicationSettings.Default.Splitter1Distance = splitContainer1.SplitterDistance;
            ApplicationSettings.Default.Splitter2Distance = splitContainer2.SplitterDistance;
            ApplicationSettings.Default.Splitter3Distance = splitContainer3.SplitterDistance;
            ApplicationSettings.Default.Thumbnailsize = MyPhotoIndexTrackBar1.Value;
            ApplicationSettings.Default.SavedScreenWidthResolution = Screen.PrimaryScreen.WorkingArea.Width;
            ApplicationSettings.Default.SavedScreenHeightResolution = Screen.PrimaryScreen.WorkingArea.Height;
            ApplicationSettings.Default.LastFilterTreeView = FolderViewToolStripMenuItem.Enabled ? 0 : 1;
            if (SortToolStripComboBox.SelectedItem != null)
            {
                ApplicationSettings.Default.LastImageSorting = SortToolStripComboBox.SelectedItem.GetType().FullName;
            }

            ApplicationSettings.Default.SortDescending = sortOrderToolStripButton.Checked;

            DynamicConfiguration.Default.Save();
        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);

            this.WindowState = FormWindowState.Maximized;
            this.Refresh();
            SplashScreen.Instance.TopMost = false;
            SplashScreen.Instance.Owner = this;

            ToolStripControlHost TrackBarContainer = new ToolStripControlHost(MyPhotoIndexTrackBar1, "ImageSizeTrackbar");
            cView1.ToolStrip.Width = 300;
            TrackBarContainer.Width = 150;
            TrackBarContainer.Overflow = ToolStripItemOverflow.Never;
            TrackBarContainer.Height = 20;
            cView1.ToolStrip.Items.Insert(1, TrackBarContainer);
            MyPhotoIndexTrackBar1.Size = new Size(150, 20);
            SortToolStripComboBox.Size = new Size(130, 10);
            toolStripSearchBox.Size = new Size(150, 10);

            toolStripSearchBox.TextChanged += new EventHandler(searchBox_TextChanged);
            toolStripSearchButton.Click += new EventHandler(toolStripSearchButton_Click);

            Manager.PluginLoadEvent += new EventHandler<PluginLoadEventArgs>(Manager_PluginLoadEvent);
            ApplicationContext.Instance.ProcessProgress = new ProcessProgress();
            ApplicationContext.Instance.SettingsManager = DynamicConfiguration.Default;
            ApplicationContext.Instance.ImageTagCollection = ImageTagCollection.Instance;
            ApplicationContext.Instance.ImageCollection = Storage.Instance;
            ApplicationContext.Instance.ImageCategoryCollection = ImageCategoryCollection.Instance;

            Manager.LoadPlugins(ApplicationContext.Instance);
            //Init the utility plugins tolls menu
            PluginsHandler.BuildPluginMenus(pluginsToolStripMenuItem, new GetActiveViewerDelegate(GetActiveViewerDelegate));

            //Connect to the photo index
            string dbPath = ApplicationSettings.Default.IndexDb;
            if (String.IsNullOrEmpty(dbPath) == true)
            {
                CreateInitialPhotoIndex();
            }

            if (ApplicationFolders.IsAppPortable == false)
            {
                dbPath = ApplicationSettings.Default.IndexDb;
            }
            else
            {
                dbPath = Path.Combine(ApplicationFolders.DefaultIndexFolder, ApplicationFolders.DefaultIndexFileName);
            }

            if (ConnectToPhotoIndex(dbPath) == false)
            {
                CloseSplashScreen();
                if (SelectPhotoIndex() == false)
                {
                    Application.Exit();
                    return;
                }
            }

            ImageCategoryCollection.Instance.Load((IImageCategoriesDataAccessProvider)DataAccessProvider.Instance);
            SavedQueriesCollection.Instance.Load((ISavedQueriesDataAccessProvider)DataAccessProvider.Instance);

            PhotoIndexUpgrader upgrader = new PhotoIndexUpgrader();
            bool indexNeedsUpgrade = upgrader.NeedUpgrade();
            bool cacheNeedsUpgrade = upgrader.ImageCacheNeedUpgrade();

            if (indexNeedsUpgrade == true ||
                cacheNeedsUpgrade == true)
            {
                CloseSplashScreen();

                try
                {
                    if (indexNeedsUpgrade == true)
                    {
                        using (m_progressForm = new AsyncProgressForm(this, Resources.Resources.UpgradingPhotoIndex, null, DataAccessProvider.Instance.GetImageListSize()))
                        {
                            upgrader.UpgradePhotoIndexData(m_progressForm);
                        }
                    }

                    if (cacheNeedsUpgrade == true)
                    {
                        using (m_progressForm = new AsyncProgressForm(this, Resources.Resources.UpgradeImageCache, null, 0))
                        {
                            upgrader.UpgradeImageCache(m_progressForm);
                        }
                    }

                }
                catch (Exception ex)
                {
                    Logger.Log(ex);
                }

                InitializeTagTreeAndImageList();
            }
            else
            {
                InitializeTagTreeAndImageList();
                CloseSplashScreen();
            }

            InitializeMainView();

            ApplicationAlert.DefaultOwner = this;
        }

        public MyPhotoIndexThumbnailViewer GetActiveViewerDelegate()
        {
            return photoThumbViewer1;
        }

        private static void CloseSplashScreen()
        {
            SplashScreen.Instance.Close();
            //while (SplashScreen.Instance.Opacity > 0)
            //{
            //    Application.DoEvents();
            //}
        }

        private void InitializeTagTreeAndImageList()
        {
            BuildTagTree();
            this.Refresh();

            Storage.Instance.LoadImageList();
            Storage.Instance.Filter((QueryParameter)null);

            UpdateStatusBar();
            UpdateMenuItemsStatus();
            BuildSaveMenu();
            BuildSavedQueriesMenu();
        }

        private void InitializeMainView()
        {
            if (ApplicationSettings.Default.FirstRun == true)
            {
                ApplicationSettings.Default.FirstRun = false;
                DynamicConfiguration.Default.Save();
            }

            if (Storage.Instance.Count == 0)
            {
                DialogResult dr = ApplicationAlert.Show(this, Resources.Resources.MainForm_EmptyIndexStartImportWizard, Resources.Resources.ApplicationName, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dr == DialogResult.Yes)
                {
                    ImageFilesImportWizard importWizard = new ImageFilesImportWizard();
                    importWizard.ShowDialog(this);

                    Storage.Instance.LoadImageList();
                    Storage.Instance.Filter((QueryParameter)null);
                }
            }

            ShowAllImages.Enabled = Storage.Instance.FilterActive;

            InitializeTagsPalette();
            InitializeProgressBar();
            BuildSharingPluginMenu();

            CheckForVersionUpdates();
        }

        void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            VersionChecker checker = new VersionChecker();
            checker.VersionCheckResponseEvent += new EventHandler<VersionCheckerEventArgs>(checker_VersionCheckResponseEvent);
            checker.CheckForNewerVersionAsync(true);
        }

        private void CheckForVersionUpdates()
        {
            if (ApplicationSettings.Default.CheckForUpdatesOnStartup == false)
            {
                return;
            }

            VersionChecker checker = new VersionChecker();
            checker.VersionCheckResponseEvent += new EventHandler<VersionCheckerEventArgs>(checker_VersionCheckResponseEvent);
            checker.CheckForNewerVersionAsync();
        }

        private delegate void ShowVersionUpdateFormDelegate(VersionCheckerEventArgs e);
        void checker_VersionCheckResponseEvent(object sender, VersionCheckerEventArgs e)
        {
            if (e.NewVersionExists == true ||
                e.Tag != null)
            {
                this.Invoke(new ShowVersionUpdateFormDelegate(ShowVersionUpdateForm), new Object[] { e });
            }
        }

        private void ShowVersionUpdateForm(VersionCheckerEventArgs e)
        {
            VersionCheckForm vcf = new VersionCheckForm(e.NewVersionExists, e.ProgramInfo);
            vcf.ShowDialog(this);
        }

        void queryMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripItem queryMenuItem = sender as ToolStripItem;
            SavedQuery savedQuery = queryMenuItem.Tag as SavedQuery;

            List<int> filteredList = savedQuery.ExecuteQuery(false);
            Storage.Instance.Filter(filteredList);
        }

        void searchBox_TextChanged(object sender, EventArgs e)
        {

        }

        void toolStripSearchButton_Click(object sender, EventArgs e)
        {
            bool isDate = false;
            bool isDateRange = false;

            String text = toolStripSearchBox.Text;
            if (String.IsNullOrEmpty(text))
            {
                Storage.Instance.Filter((QueryParameter)null);
                return;
            }

            DateTime fromDate = DateTime.MinValue;
            DateTime toDate = DateTime.MinValue;
            if (DateTime.TryParse(text, System.Threading.Thread.CurrentThread.CurrentUICulture, DateTimeStyles.None, out fromDate) == true)
            {
                isDate = true;
            }

            if (text.Contains("-") == true)
            {
                string[] parts = text.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length == 2)
                {
                    if (DateTime.TryParse(parts[0], System.Threading.Thread.CurrentThread.CurrentUICulture, DateTimeStyles.None, out fromDate) == true)
                    {
                        if (DateTime.TryParse(parts[1], System.Threading.Thread.CurrentThread.CurrentUICulture, DateTimeStyles.None, out toDate) == true)
                        {
                            isDateRange = true;
                        }
                    }
                }
            }

            List<QueryParameter> queryParameters = new List<QueryParameter>();

            if (isDate == false &&
                isDateRange == false)
            {
                CommentQueryParameter parameter = new CommentQueryParameter(text);
                parameter.Relation = QueryParameterRelation.Or;
                queryParameters.Add(parameter);

                IImageTag[] tags = ImageTagCollection.Instance.GetTagByName(text, (toolStripSearchBox.InnerControl.ListValueSelected == false));
                if (tags.Length > 0)
                {
                    foreach (IImageTag tag in tags)
                    {
                        ImageTagQueryParameter tagParameter = new ImageTagQueryParameter(tag.Id);
                        tagParameter.Relation = QueryParameterRelation.Or;
                        queryParameters.Add(tagParameter);

                        List<int> childTags = ImageTagCollection.Instance.GetTagList(tag.Id);
                        foreach (int childTagId in childTags)
                        {
                            tagParameter = new ImageTagQueryParameter(childTagId);
                            tagParameter.Relation = QueryParameterRelation.Or;
                            queryParameters.Add(tagParameter);
                        }
                    }
                }
            }
            else
                if (isDate == true)
                {
                    QueryParameter param = new ImageDateTakenQueryParameter(fromDate, QueryParameterOperation.Equal);
                    param.Relation = QueryParameterRelation.Or;
                    queryParameters.Add(param);
                }
            if (isDateRange == true)
            {
                QueryParameter fromParam = new ImageDateTakenQueryParameter(fromDate, QueryParameterOperation.GreaterThen);
                fromParam.Relation = QueryParameterRelation.And;
                queryParameters.Add(fromParam);

                QueryParameter toParam = new ImageDateTakenQueryParameter(toDate, QueryParameterOperation.LessThenEquals);
                toParam.Relation = QueryParameterRelation.And;
                queryParameters.Add(toParam);
            }

            Storage.Instance.Filter(queryParameters.ToArray());

            if (myPhotoIndexImageTagTreeView1.GetCheckedNodes().Length > 0)
            {
                myPhotoIndexImageTagTreeView1.UncheckAll();
            }
        }

        private void BuildSaveMenu()
        {
            foreach (IImageFormatProvider provider in ImageFormatProviders.Default)
            {
                if (provider.CanSave == true)
                {
                    ToolStripItem tsi = saveAsToolStripMenuItem.DropDownItems.Add(provider.Extention);
                    tsi.Tag = provider;
                    tsi.Click += new EventHandler(tsi_Click);
                }
            }
        }

        void tsi_Click(object sender, EventArgs e)
        {
            if (photoThumbViewer1.SelectedImages.Count == 0)
            {
                return;
            }

            ToolStripDropDownItem ddi = (ToolStripDropDownItem)sender;
            IImageFormatProvider provider = ddi.Tag as IImageFormatProvider;

            IImageData data = Storage.Instance[photoThumbViewer1.SelectedImages[0]];
            String fileName = Path.GetFileName(Path.ChangeExtension(data.FileName, provider.Extention));

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.FileName = fileName;
            sfd.DefaultExt = provider.Extention;
            sfd.Filter = String.Format("Image files (*.{0}) | *.{0}", provider.Extention);
            sfd.OverwritePrompt = true;
            sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            DialogResult dr = sfd.ShowDialog(this);
            if (dr != DialogResult.OK)
            {
                return;
            }

            String destination = Path.GetFileNameWithoutExtension(sfd.FileName) + "{0}";

            String caption = String.Format("{0} {1}", ddi.OwnerItem.Text, ddi.Text);
            caption = caption.Replace("&", String.Empty);
            using (AsyncProgressForm progressForm = new AsyncProgressForm(this, caption, ddi.Image, photoThumbViewer1.SelectedImages.Count * 2))
            {
                int imageNum = 0;
                List<int> selectedImages = new List<int>(photoThumbViewer1.SelectedImages);
                foreach (int selectedImageId in selectedImages)
                {
                    progressForm.Increment();
                    IImageData imageData = Storage.Instance[selectedImageId];
                    if (imageData.LinkStatus == ImageLinkStatus.Valid)
                    {
                        try
                        {
                            using (Image image = imageData.FormatProvider.LoadImage(imageData))
                            {
                                fileName = Path.ChangeExtension(String.Format(destination, (imageNum == 0) ? String.Empty : imageNum.ToString(CultureInfo.InvariantCulture)), provider.Extention);
                                provider.SaveImage(image, imageData, fileName);
                            }
                        }
                        catch (Exception ex)
                        {
                            ApplicationAlert.Show("An error has occurred while saving file");
                            Logger.Log(ex);
                        }

                        imageNum++;
                    }
                    progressForm.Increment();
                    if (progressForm.Stop == true)
                    {
                        break;
                    }
                }
            }
        }

        void FolderViewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ToggleFilterTree(true);
        }

        void TagsViewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ToggleFilterTree(false);
        }

        void ToggleFilterTree(bool folders)
        {
            ClearFilter();

            if (folders == true)
            {
                FilterTypeToolStripDropDownButton.Image = FolderViewToolStripMenuItem.Image;
                treeView1.Visible = true;
                FolderViewToolStripMenuItem.Enabled = false;
                TagsViewToolStripMenuItem.Enabled = true;
            }
            else
            {
                FilterTypeToolStripDropDownButton.Image = TagsViewToolStripMenuItem.Image;
                treeView1.Visible = false;
                FolderViewToolStripMenuItem.Enabled = true;
                TagsViewToolStripMenuItem.Enabled = false;
            }
        }

        private void BuildFolderTree()
        {
            try
            {
                FolderTreeBuilder.BuildFolderTree(treeView1, Storage.Instance);
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
        }

        void treeView1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                BuildTagCreationMenu();
                foldersViewContextMenu.Tag = treeView1.SelectedNode.Text;
                Point p = treeView1.PointToClient(Cursor.Position);
                foldersViewContextMenu.Show(treeView1, p.X, p.Y);
            }
        }

        private void BuildTagCreationMenu()
        {
            createTagToolStripMenuItem.DropDownItems.Clear();

            foreach (IImageTag imageTag in ImageTagCollection.Instance.Tags)
            {
                BuildTagCreationMenu(createTagToolStripMenuItem.DropDownItems, imageTag);
            }
        }

        private void BuildTagCreationMenu(ToolStripItemCollection toolStripItemCollection, IImageTag imageTag)
        {
            ToolStripMenuItem item = toolStripItemCollection.Add(imageTag.Name) as ToolStripMenuItem;
            item.Tag = imageTag;
            item.Click += new EventHandler(item_Click);

            foreach (IImageTag childTag in imageTag.ChildTags)
            {
                BuildTagCreationMenu(item.DropDownItems, childTag);
            }
        }

        void item_Click(object sender, EventArgs e)
        {
            foldersViewContextMenu.Hide();
            String tagName = foldersViewContextMenu.Tag as String;
            ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
            IImageTag newTag = ImageTagCollection.Instance.Create(menuItem.Tag as IImageTag, tagName);
            ImageTagCollection.Instance.SaveTag(newTag);

            BuildTagTree();

            List<int> images = new List<int>();
            foreach (IImageData imageData in Storage.Instance)
            {
                images.Add(imageData.Id);
            }

            Storage.Instance.AddRemoveImageTags(images.AsReadOnly(), new int[] { newTag.Id }, true);
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            String queryParam = e.Node.FullPath;
            //take care of root paths
            if (queryParam.Length == 2 &&
                queryParam.EndsWith(string.Format("{0}", Path.DirectorySeparatorChar)) == false)
            {
                queryParam += Path.DirectorySeparatorChar;
            }
            DirectoryNameQueryParameter queryParameter = new DirectoryNameQueryParameter(queryParam);

            QueryParameter[] queryParametersArray = new QueryParameter[] { queryParameter };
            Storage.Instance.Filter(queryParametersArray);
            Cursor.Current = Cursors.Default;
        }

        void Manager_PluginLoadEvent(object sender, PluginLoadEventArgs e)
        {
            Application.DoEvents();
        }

        void Instance_FilterChangedEvent(object sender, EventArgs e)
        {
            this.Invoke(new voidDelegate(FilterChangedInvoked));
        }

        void FilterChangedInvoked()
        {
            photoThumbViewer1.Refresh();
            UpdateStatusBar();
            ShowAllImages.Enabled = Storage.Instance.FilterActive;
        }

        void Instance_ImageCollectionLoadedEvent(object sender, EventArgs e)
        {
            m_selectedImages.Clear();
            photoThumbViewer1.Refresh();
            BuildFolderTree();

            UpdateStatusBar();

            toolStripSearchBox.InnerControl.StartDate = Storage.Instance.StartDate;
            toolStripSearchBox.InnerControl.EndDate = Storage.Instance.EndDate;
            toolStripSearchBox.InnerControl.MarkedDates = Storage.Instance.ValidDates.ToArray();
        }

        void Instance_ImageCollectionLoadingEvent(object sender, EventArgs e)
        {
            Application.DoEvents();
        }
        static readonly Guid CLSID_AutoComplete = new Guid("{00BB2763-6A77-11D0-A535-00C04FD7D062}");

        void BuildTagTree()
        {
            ImageTagCollection tagFactory = ImageTagCollection.Instance;
            tagFactory.Load((ITagsDataAccessProvider)DataAccessProvider.Instance);
            myPhotoIndexImageTagTreeView1.Load(tagFactory);

            List<IImageTag> tags = tagFactory.Tags;

            foreach (IImageTag tag in tags)
            {
                List<int> subTags = ImageTagCollection.Instance.GetTagList(tag.Id);
                foreach (int subTag in subTags)
                {
                    toolStripSearchBox.InnerControl.AutoCompleteCustomSource.Add(ImageTagCollection.Instance[subTag].Name);
                }
            }
        }

        void Instance_ImageTagCollectionLoaded(object sender, EventArgs e)
        {
            ImageTagCollection tagFactory = ImageTagCollection.Instance;
            myPhotoIndexImageTagTreeView1.Load(tagFactory);
        }

        void Instance_ImageCategoryCollectionLoadedEvent(object sender, EventArgs e)
        {
            BuildImageCategoriesMenu();
        }

        private void BuildImageCategoriesMenu()
        {
            List<ToolStripItem> removeList = new List<ToolStripItem>();
            foreach (ToolStripItem item in categoriesContextMenuStrip.Items)
            {
                if (item.Tag is IImageCategory)
                {
                    removeList.Add(item);
                }
            }

            foreach (ToolStripItem item in removeList)
            {
                categoriesContextMenuStrip.Items.Remove(item);
            }

            IImageCategoryCollection categories = ImageCategoryCollection.Instance;
            int i = 0;
            foreach (IImageCategory category in categories)
            {
                ToolStripItem tti = new ToolStripMenuItem(category.Description, m_categoriesImageList.Images[category.ColorIndex]);
                tti.Tag = category;
                tti.Click += new EventHandler(tti_Click);
                categoriesContextMenuStrip.Items.Insert(i++, tti);
            }
        }

        void tti_Click(object sender, EventArgs e)
        {
            ReadOnlyCollection<int> selectedImages = (ReadOnlyCollection<int>)categoriesContextMenuStrip.Tag;

            ToolStripMenuItem tsdi = (ToolStripMenuItem)sender;
            IImageCategory imagecategory = (IImageCategory)tsdi.Tag;
            Storage.Instance.UpdateImageCategories(selectedImages, imagecategory.Id, (tsdi.Checked == false));
        }

        internal void UpdateStatusBar()
        {
            String statusBarContent = String.Format(Resources.Resources.StstusBarImageCount, Storage.Instance.Count, Storage.Instance.UnFiltered.Count);

            int numSelected = photoThumbViewer1.SelectedImages.Count;
            String imageInfo = String.Empty;
            if (numSelected == 1)
            {
                IImageData imageData = Storage.Instance[photoThumbViewer1.SelectedImages[0]];
                if (imageData != null)
                {
                    String fileName = Path.GetFileName(imageData.FileName);
                    imageInfo = String.Format("{0} {1}x{2}", fileName, imageData.ImageSize.Width, imageData.ImageSize.Height);
                }
            }
            else
                if (numSelected > 1)
                {
                    imageInfo = String.Format("{0} {1}", numSelected, Resources.Resources.SelectedImages);
                }

            if (String.IsNullOrEmpty(imageInfo) == false)
            {
                statusBarContent += "    -    " + imageInfo;
            }

            ImageCountLabel.Text = statusBarContent;
        }

        private void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
        {
            splitContainer1.Panel1.Refresh();
        }

        private void splitContainer2_SplitterMoved(object sender, SplitterEventArgs e)
        {
            AdjustSelectedImagesPane();
        }

        void photoThumbViewer1_ThumbnailDragDropEvent(object sender, ThumbnailDragDropEventArgs e)
        {
            List<int> tagList = new List<int>();
            TreeNode selectedtagNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
            if (selectedtagNode != null &&
                myPhotoIndexImageTagTreeView1.SelectedNodes.Contains(selectedtagNode) == true)
            {
                foreach (TreeNode node in myPhotoIndexImageTagTreeView1.SelectedNodes)
                {
                    if (node.Parent != null)
                    {
                        int tagId = Convert.ToInt32(node.Name, CultureInfo.InvariantCulture);
                        tagList.Add(tagId);
                    }
                }
            }
            else
                if (selectedtagNode == null)
                {
                    Thumbnail thumbnail = (Thumbnail)e.Data.GetData(typeof(Thumbnail));
                    if (thumbnail != null)
                    {
                        if (thumbnail.Parent.SelectedImages.Contains(thumbnail.ImageId) == true)
                        {
                            foreach (int tagId in thumbnail.Parent.SelectedImages)
                            {
                                tagList.Add(tagId);
                            }
                        }
                        else
                        {
                            tagList.Add(thumbnail.ImageId);
                        }
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    int tagId = Convert.ToInt32(selectedtagNode.Name, CultureInfo.InvariantCulture);
                    tagList.Add(tagId);
                }

            ReadOnlyCollection<int> selectedCollection = null;
            if (photoThumbViewer1.IsSelected(e.ImageId) == true)
            {
                selectedCollection = photoThumbViewer1.SelectedImages;
            }
            else
            {
                selectedCollection = new ReadOnlyCollection<int>(new int[] { e.ImageId });
            }

            photoThumbViewer1.FlashThumbnailTagIcons(new List<int>(selectedCollection).ToArray());
            Storage.Instance.AddRemoveImageTags(selectedCollection, tagList.ToArray(), true);

            foreach (int tagId in tagList)
            {
                IImageTag tag = myPhotoIndexImageTagTreeView1.GetTag(tagId);
                if (tag.Thumbnail == null)
                {
                    tag.Thumbnail = new Bitmap(Storage.Instance[selectedCollection[0]].Thumbnail);
                    ImageTagCollection.Instance.SaveTag(tag);
                }
            }
        }

        void photoThumbViewer1_ThumbnailDragLeaveEvent(object sender, EventArgs e)
        {
            Win32Interop.ImageDragHelper.ImageList_DragLeave(this.photoThumbViewer1.Handle);
        }

        void photoThumbViewer1_ThumbnailDragEnterEvent(object sender, DragEventArgs e)
        {
            Win32Interop.ImageDragHelper.ImageList_DragEnter(this.photoThumbViewer1.Handle, e.X - this.photoThumbViewer1.Left, e.Y - this.photoThumbViewer1.Top);
        }

        void photoThumbViewer1_ThumbnailDragOverEvent(object sender, ThumbnailDragDropEventArgs e)
        {
            // Compute drag position and move image
            Point point = photoThumbViewer1.PointToClient(new Point(e.X, e.Y));
            Win32Interop.ImageDragHelper.ImageList_DragMove(point.X, point.Y);

            e.Effect = DragDropEffects.None;

            if (e.ImageId < 0)
            {
                return;
            }

            TreeNode tn = (TreeNode)e.Data.GetData(typeof(TreeNode));
            if (tn != null)
            {
                if (myPhotoIndexImageTagTreeView1.SelectedNodes.Contains(tn) == false)
                {
                    if (tn.Parent != null)
                    {
                        e.Effect = DragDropEffects.Link;
                    }
                }
                else
                {
                    foreach (TreeNode node in myPhotoIndexImageTagTreeView1.SelectedNodes)
                    {
                        if (node.Parent != null)
                        {
                            e.Effect = DragDropEffects.Link;
                        }
                    }
                }
            }
            else
            {
                Thumbnail thumbnail = (Thumbnail)e.Data.GetData(typeof(Thumbnail));
                if (thumbnail != null &&
                    e.ImageId > -1 &&
                    thumbnail.ImageData.GetType() != typeof(ImageData))
                {
                    e.Effect = DragDropEffects.Link;
                }
                else
                {
                    e.Effect = DragDropEffects.None;
                }
            }
        }

        private void photoThumbViewer1_ThumbnailMouseClickEvent(object sender, ThumbnailMouseEventArgs e)
        {
            m_toolTip.Hide(photoThumbViewer1);
            m_toolTip.Dispose();

            if (e.MouseButton == MouseButtons.Right &&
                e.ThumbnailIcon == ThumbnailIcon.Invalid)
            {
                ToolStripMenuItem removeTagMenuItem = rcMenuRemoveTag;
                BuidMenuRemoveTagList(removeTagMenuItem, photoThumbViewer1.SelectedImages);
                BuildMenuAddTagList(addTagToolStripMenuItem, photoThumbViewer1.SelectedImages);
                imageContextMenu.Tag = sender;

                imageContextMenu.Show(photoThumbViewer1, e.X, e.Y);
            }
            else
                if (e.MouseButton == MouseButtons.Right &&
                    e.ThumbnailIcon == ThumbnailIcon.Tag)
                {
                    ReadOnlyCollection<int> selectedImages = new ReadOnlyCollection<int>(new int[] { e.ImageId });
                    ToolStripMenuItem removeTagMenuItem = (ToolStripMenuItem)tagContextMenu.Items["removeTagToolStripMenuItem"];
                    BuidMenuRemoveTagList(removeTagMenuItem, selectedImages);
                    tagContextMenu.Show(photoThumbViewer1, e.X, e.Y);
                }
                else
                    if (e.MouseButton == MouseButtons.Left &&
                        e.ThumbnailIcon == ThumbnailIcon.Categories)
                    {

                        ReadOnlyCollection<int> selectedImages = null;
                        if (photoThumbViewer1.IsSelected(e.ImageId))
                        {
                            selectedImages = photoThumbViewer1.SelectedImages;
                        }
                        else
                        {
                            selectedImages = new ReadOnlyCollection<int>(new int[] { e.ImageId });
                        }

                        HighlightImageCategoriesMenu(categoriesContextMenuStrip, selectedImages);
                        categoriesContextMenuStrip.Tag = selectedImages;
                        categoriesContextMenuStrip.Show(photoThumbViewer1, e.X, e.Y);
                    }
                    else
                        if (e.MouseButton == MouseButtons.Left &&
                            e.ThumbnailIcon == ThumbnailIcon.Info)
                        {
                            photoThumbViewer1.ToggleImageInfo(e.ImageId, true);
                        }
                        else
                            if (e.MouseButton == MouseButtons.Left &&
                                e.ThumbnailIcon == ThumbnailIcon.Rating)
                            {
                                ReadOnlyCollection<int> selectedImages = new ReadOnlyCollection<int>(new int[] { e.ImageId });
                                ratingContextMenu.Tag = selectedImages;
                                ratingContextMenu.Show(photoThumbViewer1, e.X, e.Y);
                            }
                            else
                                if (e.MouseButton == MouseButtons.Left &&
                                    e.ThumbnailIcon == ThumbnailIcon.Play)
                                {
                                    IImageData imageData = Storage.Instance[e.ImageId];

                                    if (m_currentVideoPlayer != null)
                                    {
                                        m_currentVideoPlayer.Stop();
                                        Thumbnail oldThumbnail = (Thumbnail)m_currentVideoPlayer.Tag;
                                        if (oldThumbnail != null &&
                                            oldThumbnail.VideoPlaying == true)
                                        {
                                            oldThumbnail.VideoPlaying = false;
                                            this.photoThumbViewer1.Invalidate(oldThumbnail.FrameDrawingRect);
                                        }
                                    }

                                    if (imageData.LinkStatus == ImageLinkStatus.Invalid)
                                    {
                                        return;
                                    }

                                    IVideoFormatProvider provider = (IVideoFormatProvider)imageData.FormatProvider;
                                    if (provider != null)
                                    {
                                        try
                                        {
                                            m_currentVideoPlayer = provider.CreateVideoPlayer(imageData.FileName, photoThumbViewer1, e.FrameRect);
                                            m_currentVideoPlayer.StatusChanged += new EventHandler(m_currentVideoPlayer_StatusChanged);

                                        }
                                        catch (FileNotFoundException fnfex)
                                        {
                                            Logger.Log(fnfex);
                                            imageData.LinkStatus = ImageLinkStatus.Invalid;
                                            imageData.InvokeChangedEvent();
                                            return;
                                        }

                                        Thumbnail thumbnail = (Thumbnail)sender;
                                        thumbnail.ImageDrawingRectCahngedEvent += new EventHandler<EventArgs>(thumbnail_ImageDrawingRectCahngedEvent);
                                        thumbnail.DisposingEvent += new EventHandler<EventArgs>(thumbnail_DisposingEvent);
                                        m_currentVideoPlayer.Tag = thumbnail;
                                        thumbnail.VideoPlaying = true;

                                        this.photoThumbViewer1.Invalidate(thumbnail.FrameDrawingRect);

                                        m_currentVideoPlayer.Play();
                                    }
                                }
                                else
                                    if (e.MouseButton == MouseButtons.Left &&
                                        e.ThumbnailIcon == ThumbnailIcon.Stop)
                                    {
                                        Thumbnail thumbnail = (Thumbnail)sender;
                                        if (m_currentVideoPlayer != null &&
                                            thumbnail.VideoPlaying == true)
                                        {
                                            m_currentVideoPlayer.Stop();
                                            this.photoThumbViewer1.Invalidate(thumbnail.FrameDrawingRect);
                                            thumbnail.VideoPlaying = false;
                                        }
                                    }
                                    else
                                        if (e.MouseButton == MouseButtons.Left &&
                                            e.ThumbnailIcon == ThumbnailIcon.DateText)
                                        {
                                            PopupThumbnailInfoTextContextMenu(e.X, e.Y);
                                        }
        }

        private void HighlightImageCategoriesMenu(ContextMenuStrip categoriesContextMenuStrip, ReadOnlyCollection<int> selectedImages)
        {
            List<int> selectedCategoryIds = new List<int>();
            Dictionary<int, int> counter = new Dictionary<int, int>();

            foreach (int imageId in selectedImages)
            {
                IImageData imageData = Storage.Instance[imageId];
                if (imageData != null)
                {
                    foreach (int categoryId in imageData.Categories)
                    {
                        if (categoryId > 0 &&
                            selectedCategoryIds.Contains(categoryId) == false)
                        {
                            selectedCategoryIds.Add(categoryId);
                        }

                        int count = 0;
                        if (counter.TryGetValue(categoryId, out count) == true)
                        {
                            counter.Remove(categoryId);
                            count++;
                        }
                        else
                        {
                            count = 1;
                        }

                        counter.Add(categoryId, count);
                    }
                }
            }

            List<int> removeList = new List<int>();
            foreach (int categoryId in selectedCategoryIds)
            {
                if (counter[categoryId] < selectedImages.Count)
                {
                    removeList.Add(categoryId);
                }
            }

            foreach (int categoryId in removeList)
            {
                selectedCategoryIds.Remove(categoryId);
            }

            foreach (ToolStripItem tsi in categoriesContextMenuStrip.Items)
            {
                if (tsi is ToolStripMenuItem &&
                    tsi.Tag != null)
                {
                    ToolStripMenuItem tsdi = (ToolStripMenuItem)tsi;
                    IImageCategory imagecategory = (IImageCategory)tsdi.Tag;
                    tsdi.Checked = (selectedCategoryIds.Contains(imagecategory.Id) == true);
                }
            }
        }

        void m_currentVideoPlayer_StatusChanged(object sender, EventArgs e)
        {
            IVideoPlayer player = sender as IVideoPlayer;
            if (player.Tag != null &&
                player.Status == VideoPlayerStatus.Stopped)
            {
                Thumbnail thumb = player.Tag as Thumbnail;
                thumb.VideoPlaying = false;
                this.photoThumbViewer1.Invalidate(thumb.FrameDrawingRect);
            }
        }

        private void BuildMenuAddTagList(ToolStripMenuItem addTagToolStripMenuItem, ReadOnlyCollection<int> selectedImages)
        {
            if (addTagToolStripMenuItem.DropDownItems.Count > 0)
            {
                return;
            }

            foreach (IImageTag imageTag in ImageTagCollection.Instance.Tags)
            {
                BuildMenuAddTagList(addTagToolStripMenuItem, imageTag, selectedImages);
            }
        }

        private void BuildMenuAddTagList(ToolStripMenuItem toolStripItem, IImageTag imageTag, ReadOnlyCollection<int> selectedImages)
        {
            Image menuIcon = null;
            if (imageTag.Thumbnail != null)
            {
                try
                {
                    menuIcon = new Bitmap(imageTag.Thumbnail, 32, 32);
                }
                catch
                {
                    menuIcon = new Bitmap(32, 32);
                }
            }
            else
            {
                menuIcon = new Bitmap(32, 32);
            }

            ToolStripMenuItem item = toolStripItem.DropDownItems.Add(imageTag.Name, menuIcon) as ToolStripMenuItem;
            item.ImageScaling = ToolStripItemImageScaling.None;

            if (toolStripItem != addTagToolStripMenuItem)
            {
                item.Tag = new AddTagsData(imageTag, selectedImages);
                item.Click += new EventHandler(AddTagMenuItem_Click);
            }

            foreach (IImageTag childTag in imageTag.ChildTags)
            {
                BuildMenuAddTagList(item, childTag, selectedImages);
            }
        }

        void AddTagMenuItem_Click(object sender, EventArgs e)
        {
            imageContextMenu.Hide();

            ToolStripMenuItem item = sender as ToolStripMenuItem;
            AddTagsData data = item.Tag as AddTagsData;

            Storage.Instance.AddRemoveImageTags(data.ImageList, new int[] { data.ImageTag.Id }, true);
        }

        void photoThumbViewer1_ThumbnailMouseDoubleClickEvent(object sender, ThumbnailMouseEventArgs e)
        {
            if (MyPhotoIndexTrackBar1.Value == 1)
            {
                toolStripGoBack_Click();
                return;
            }

            photoThumbViewer1.ClearSelection();
            photoThumbViewer1.SelectImage(e.ImageId, true);
            toolStripLargest_Click();
        }

        void thumbnail_DisposingEvent(object sender, EventArgs e)
        {
            if (m_currentVideoPlayer != null &&
                m_currentVideoPlayer.Tag == sender)
            {
                m_currentVideoPlayer.Stop();
            }
        }

        void thumbnail_ImageDrawingRectCahngedEvent(object sender, EventArgs e)
        {
            if (m_currentVideoPlayer != null)
            {
                Thumbnail thumbnail = (Thumbnail)m_currentVideoPlayer.Tag;
                m_currentVideoPlayer.Position = thumbnail.ImageDrawingRect;
            }
        }

        void myPhotoIndexImageTagTreeView1_DragOver(object sender, DragEventArgs e)
        {
            Point point = myPhotoIndexImageTagTreeView1.PointToClient(new Point(e.X, e.Y));
            Win32Interop.ImageDragHelper.ImageList_DragMove(point.X, point.Y);

            TreeNode selectedtagNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
            MyPhotoIndex.Controls.TreeView tv = (MyPhotoIndex.Controls.TreeView)sender;
            TreeNode droppedOnNode = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y)));

            if (droppedOnNode != null &&
                selectedtagNode != null &&
                droppedOnNode != selectedtagNode &&
                droppedOnNode != selectedtagNode.Parent &&
                selectedtagNode.Parent != null &&
                IsParentTagOf(selectedtagNode, droppedOnNode) == false)
            {
                e.Effect = DragDropEffects.Link;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private bool IsParentTagOf(TreeNode selectedtagNode, TreeNode droppedOnNode)
        {
            if (droppedOnNode.Parent != null)
            {
                if (droppedOnNode.Parent == selectedtagNode)
                {
                    return true;
                }

                return IsParentTagOf(selectedtagNode, droppedOnNode.Parent);
            }

            return false;
        }

        void myPhotoIndexImageTagTreeView1_DragDrop(object sender, DragEventArgs e)
        {
            TreeNode selectedtagNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
            MyPhotoIndex.Controls.TreeView tv = (MyPhotoIndex.Controls.TreeView)sender;
            TreeNode droppedOnNode = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y)));

            if (selectedtagNode == null ||
                droppedOnNode == null ||
                droppedOnNode == selectedtagNode ||
                droppedOnNode == selectedtagNode.Parent &&
                IsParentTagOf(selectedtagNode, droppedOnNode) == false)
            {
                return;
            }

            if (ApplicationSettings.Default.ShowTagParentChangeMessage == true)
            {
                CheckBoxParameters checkBoxParameters = new CheckBoxParameters();
                checkBoxParameters.Text = Resources.Resources.ShowWarningNextTime;
                checkBoxParameters.Value = true;

                DialogResult dr = ApplicationAlert.Show(string.Format(Resources.Resources.TagChangedParent, selectedtagNode.Text), Resources.Resources.ApplicationName, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, ref checkBoxParameters);

                if (dr != DialogResult.OK)
                {
                    return;
                }

                if (checkBoxParameters.Value == false)
                {
                    ApplicationSettings.Default.ShowTagParentChangeMessage = false;
                    ApplicationSettings.Default.Save();
                }
            }

            ImageTag tag = (ImageTag)selectedtagNode.Tag;
            if (tag.Parent != null)
            {
                tag.Parent.ChildTags.Remove(tag);
            }
            tag.Parent = (ImageTag)droppedOnNode.Tag;
            ImageTagCollection.Instance.SaveTag(tag);
            selectedtagNode.Parent.Nodes.Remove(selectedtagNode);
            droppedOnNode.Nodes.Add(selectedtagNode);

            myPhotoIndexImageTagTreeView1.UpdateTreeNodesHeight();
        }

        void myPhotoIndexImageTagTreeView1_DragLeave(object sender, EventArgs e)
        {
            Win32Interop.ImageDragHelper.ImageList_DragLeave(this.myPhotoIndexImageTagTreeView1.Handle);
        }

        void myPhotoIndexImageTagTreeView1_DragEnter(object sender, DragEventArgs e)
        {
            Win32Interop.ImageDragHelper.ImageList_DragEnter(this.myPhotoIndexImageTagTreeView1.Handle, e.X - this.myPhotoIndexImageTagTreeView1.Left, e.Y - this.myPhotoIndexImageTagTreeView1.Top);
        }

        private void AdjustSelectedImagesPane()
        {
            if (m_selectedImages == null)
            {
                return;
            }

            SelectedThumbnailViewer.ImageList = m_selectedImages;
            if (1 == m_selectedImages.Count)
            {
                SelectedThumbnailViewer.ImageColumns = 1;
            }
            else
            {
                SelectedThumbnailViewer.ImageColumns = 2;
            }

            if (SelectedThumbnailViewer.NumberOfImagesDisplayed < m_selectedImages.Count)
            {
                SelectedThumbnailViewer.ImageColumns = 3;
            }

            bool enableButtons = (SelectedThumbnailViewer.ImageList.Count > 0);
            Mail.Enabled = enableButtons;
            Print.Enabled = enableButtons;
            ClearSelectedToolStripButton.Enabled = enableButtons;
            SyncSelectedToolStripButton.Enabled = enableButtons;

            clearTagsPaletteToolStripButton.Enabled = (tagsPaletteThumbnailViewer.ImageList != null) ? (tagsPaletteThumbnailViewer.ImageList.Count > 0) : false;
        }

        void photoThumbViewer1_ThumbnailIconMouseEnterEvent(object sender, ThumbnailMouseEventArgs e)
        {
            if (e.ThumbnailIcon == ThumbnailIcon.Tag ||
                e.ThumbnailIcon == ThumbnailIcon.Categories)
            {
                IImageData imageData = photoThumbViewer1.ImageList[e.ImageId];
                if (imageData != null)
                {
                    String toolTipString = String.Empty;

                    if (e.ThumbnailIcon == ThumbnailIcon.Tag)
                    {
                        #region Tags
                        foreach (int tagId in imageData.Tags)
                        {
                            IImageTag tagInfo = ImageTagCollection.Instance.GetTag(tagId);
                            if (tagInfo != null)
                            {
                                String tagName = String.Empty;
                                if (tagInfo.UniqueName == false)
                                {
                                    tagName = tagInfo.Path;
                                }
                                else
                                {
                                    tagName = tagInfo.Name;
                                }

                                toolTipString += tagName + Environment.NewLine;
                            }
                        }
                        #endregion
                    }
                    else
                    {
                        #region Categories
                        foreach (int categoryId in imageData.Categories)
                        {
                            IImageCategory categoryInfo = ImageCategoryCollection.Instance.GetById(categoryId);
                            if (categoryInfo != null)
                            {
                                toolTipString += categoryInfo.Description + Environment.NewLine;
                            }
                        }
                        #endregion
                    }

                    if (String.IsNullOrEmpty(toolTipString) == false)
                    {
                        toolTipString = toolTipString.Substring(0, toolTipString.Length - 2);
                        Point pos = photoThumbViewer1.PointToClient(Cursor.Position);
                        pos.X += 15;
                        pos.Y += 5;
                        m_toolTip = new ToolTip();
                        m_toolTip.Show(toolTipString, photoThumbViewer1, pos);
                    }
                    else
                    {
                        m_toolTip.Hide(photoThumbViewer1);
                        m_toolTip.Dispose();
                    }
                }
            }
            else
            {
                m_toolTip.Hide(myPhotoIndexImageTagTreeView1);
                m_toolTip.Dispose();
            }
        }

        void photoThumbViewer1_ThumbnailIconMouseLeaveEvent(object sender, ThumbnailMouseEventArgs e)
        {
            m_toolTip.Hide(this);
            m_toolTip.Dispose();
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            SwitchIndex();
        }

        private void fromDiskToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ImageFilesImportWizard importWizard = new ImageFilesImportWizard();
            importWizard.ShowDialog(this);
        }

        private void fromCameraToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CameraImportWizard cameraImportWizard = new CameraImportWizard();
            cameraImportWizard.ShowDialog(this);
        }

        private void myPhotoIndexImageTagTreeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            TreeNode[] checkedNodes = myPhotoIndexImageTagTreeView1.GetCheckedNodes();
            if (checkedNodes.Length == 0)
            {
                Storage.Instance.Filter((QueryParameter)null);
                Cursor.Current = Cursors.Default;
                return;
            }

            List<TreeNode> filteredNodes = new List<TreeNode>(myPhotoIndexImageTagTreeView1.FilteredNodes);

            List<int> withAnd = new List<int>();
            List<int> withOr = new List<int>();
            List<int> without = new List<int>();

            foreach (TreeNode node in checkedNodes)
            {
                if (filteredNodes.Contains(node) == true)
                {
                    without.Add(Convert.ToInt32(node.Name, CultureInfo.InvariantCulture));
                }
                else
                {
                    if (node.Parent != null &&
                       (node.Parent.Checked == true || node.Nodes.Count > 0))
                    {
                        withOr.Add(Convert.ToInt32(node.Name));
                    }
                    else
                    {
                        withAnd.Add(Convert.ToInt32(node.Name));
                    }
                }
            }

            SavedQuery savedQuery = new SavedQuery();
            savedQuery.WithAnd = withAnd.ToArray();
            savedQuery.WithOr = withOr.ToArray();
            savedQuery.Without = without.ToArray();

            List<int> imageList = savedQuery.ExecuteQuery(true);
            Storage.Instance.Filter(imageList);

            Cursor.Current = Cursors.Default;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            photoThumbViewer1.SelectAll();
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            rcMenuCopy_Click(this, EventArgs.Empty);
        }

        private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PrintImages(false);
        }

        private void PrintImages(bool useSelectedPane)
        {
            bool validPrintersInstalled = Utilities.Printing.IsValidPrinterInstalled();
            if (validPrintersInstalled == false)
            {
                ApplicationAlert.Show(this, Resources.Resources.NoPrintersInstalled, Resources.Resources.ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            List<IImageData> images = new List<IImageData>();
            if (useSelectedPane == true)
            {
                foreach (ImageData imageData in SelectedThumbnailViewer.ImageList)
                {
                    images.Add(imageData);
                }
            }
            else
            {
                foreach (int imageId in photoThumbViewer1.SelectedImages)
                {
                    images.Add(photoThumbViewer1.ImageList[imageId]);
                }
            }

            PrintForm printForm = null;

            try
            {
                printForm = new PrintForm(images.AsReadOnly());
                DialogResult result = printForm.ShowDialog(this);
                if (result == DialogResult.Cancel)
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }

            printDialog1.Document = printForm.SelectedPlugin.GetPrintDocument(images.AsReadOnly());
            DialogResult dr = printDialog1.ShowDialog(this);
            if (dr == DialogResult.OK)
            {
                if (ApplicationSettings.Default.UsePrintPreviewInsteadOfPrinter == true)
                {
                    PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
                    printPreviewDialog.ShowIcon = true;
                    printPreviewDialog.UseAntiAlias = true;

                    using (printPreviewDialog.Document = printForm.SelectedPlugin.GetPrintDocument(images.AsReadOnly()))
                    {
                        printPreviewDialog.ShowDialog(this);
                    }
                }
                else
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(PrintAsync), printDialog1.Document);
                }
            }
        }

        void PrintAsync(Object printObject)
        {
            try
            {
                using (PrintDocument printDoc = printObject as PrintDocument)
                {
                    ApplicationContext.Instance.ProcessProgress.IsInfinite = true;
                    ApplicationContext.Instance.ProcessProgress.Running = true;
                    printDoc.Print();
                    ApplicationContext.Instance.ProcessProgress.Running = false;
                }
            }
            catch (Exception ex)
            {
                ApplicationContext.Instance.ProcessProgress.Alert(ProcessAlertType.Error, Resources.Resources.PrintFailed, Resources.Resources.PrintFailed, string.Empty);
                ApplicationContext.Instance.ProcessProgress.Running = false;
                Logger.Log(ex);
            }
        }

        private void printToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PrintImages(false);
        }

        private void mnuLangEnglish_Click(object sender, EventArgs e)
        {
            ApplicationSettings.Default.DefaultLanguage = "en-US";
            DynamicConfiguration.Default.Save();

            UpdateLanguageMenus();
        }

        private void mnuLangHebrew_Click(object sender, EventArgs e)
        {
            ApplicationSettings.Default.DefaultLanguage = "he-IL";
            DynamicConfiguration.Default.Save();

            UpdateLanguageMenus();
        }

        void lithuanianToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplicationSettings.Default.DefaultLanguage = "lt-LT";
            DynamicConfiguration.Default.Save();

            UpdateLanguageMenus();
        }

        private void UpdateLanguageMenus()
        {
            mnuLangEnglish.Checked = false;
            mnuLangHebrew.Checked = false;
            lithuanianToolStripMenuItem.Checked = false;

            String currentUICulture = ApplicationSettings.Default.DefaultLanguage;
            switch (currentUICulture)
            {
                case "en-US":
                    mnuLangEnglish.Checked = true;
                    break;

                case "he-IL":
                    mnuLangHebrew.Checked = true;
                    break;

                case "lt-LT":
                    lithuanianToolStripMenuItem.Checked = true;
                    break;
            }
        }

        private void cView3_ToolStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Name)
            {
                case "Mail":
                    ShareImages(true);
                    break;

                case "Print":
                    PrintImages(true);
                    break;

                case "ClearSelectedToolStripButton":
                    ClearSelectedPane();
                    break;

                case "SyncSelectedToolStripButton":
                    SyncSelectedImages();
                    break;
            }
        }

        private void SyncSelectedImages()
        {
            photoThumbViewer1.ClearSelection();
            List<int> selectedImages = new List<int>();

            foreach (IImageData imageData in SelectedThumbnailViewer.ImageList)
            {
                selectedImages.Add(imageData.Id);
            }

            photoThumbViewer1.SelectImage(selectedImages.ToArray());


            if (ApplicationSettings.Default.FilterSyncronizedSelection == true)
            {
                myPhotoIndexImageTagTreeView1.UncheckAll();
                toolStripSearchBox.Text = String.Empty;
                Storage.Instance.Filter(selectedImages);
            }
        }

        private void cView2_ToolStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Name)
            {
                case "ShowAllImages":
                    tsbShowAllImages_Click();
                    break;

                case "UnTaggedItemsToolStripButton":
                    FindUnTaggedItems();
                    break;

                case "AddTagCategory":
                    AddNewTagCategory();
                    break;
            }
        }

        private void AddNewTagCategory()
        {
            IImageTag newTag = ImageTagCollection.Instance.Create(null, Resources.Resources.TagTree_NewTag);

            TagEdit tef = new TagEdit(newTag, null);
            tef.Left = MousePosition.X;
            DialogResult dr = tef.ShowDialog(this);
            if (dr == DialogResult.OK)
            {
                ImageTagCollection.Instance.SaveTag(newTag);
                TreeNode childNode = myPhotoIndexImageTagTreeView1.Nodes.Add(newTag.Id.ToString(CultureInfo.InvariantCulture), newTag.Name);
                childNode.Tag = newTag;
                myPhotoIndexImageTagTreeView1.UpdateTreeNodesHeight();
                childNode.EnsureVisible();
            }
        }

        private void tsbShowAllImages_Click()
        {
            ClearFilter();
        }

        public void ClearFilter()
        {
            Storage.Instance.ClearFilter();
            myPhotoIndexImageTagTreeView1.UncheckAll();
            toolStripSearchBox.Text = String.Empty;
        }

        private void tsbLastWeek_Click()
        {
            Cursor.Current = Cursors.WaitCursor;
            Storage.Instance.Filter(new ImageDateTakenQueryParameter(DateTime.Now.AddDays(-7D), QueryParameterOperation.GreaterThen));
            datePicktoolStripSplitButton.Image = LastWeek.Image;
            Cursor.Current = Cursors.Default;
        }

        private void tsbLastMonth_Click()
        {
            Cursor.Current = Cursors.WaitCursor;
            Storage.Instance.Filter(new ImageDateTakenQueryParameter(DateTime.Now.AddMonths(-1), QueryParameterOperation.GreaterThen));
            datePicktoolStripSplitButton.Image = LastMonth.Image;

            Cursor.Current = Cursors.Default;
        }

        private static void FindUnTaggedItems()
        {
            Cursor.Current = Cursors.WaitCursor;
            Storage.Instance.Filter(new UntaggedImagesQueryParameter());
            Cursor.Current = Cursors.Default;
        }

        private void cView1_ToolStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Name)
            {
                case "GoBack":
                    toolStripGoBack_Click();
                    break;

                case "Smallest":
                    toolStripSmallest_Click();
                    break;

                case "Largest":
                    toolStripLargest_Click();
                    break;
            }
        }

        void LastWeek_Click(object sender, EventArgs e)
        {
            tsbLastWeek_Click();
        }

        void LastMonth_Click(object sender, EventArgs e)
        {
            tsbLastMonth_Click();
        }

        private void MyPhotoIndexTrackBar1_ValueChanged(object sender, EventArgs e)
        {
            int newValue = MyPhotoIndexTrackBar1.Value;

            photoThumbViewer1.ExtendNumberOfRows = (newValue > 1);
            photoThumbViewer1.ImageColumns = newValue;

            if (newValue == 1)
            {
                photoThumbViewer1.ShowPhotoBar();
            }
            else
            {
                photoThumbViewer1.HidePhotoBar();
            }
        }

        void sortAlphaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ApplicationSettings.Default.ShowTagSortMessage == true)
            {
                CheckBoxParameters checkBoxParameters = new CheckBoxParameters();
                checkBoxParameters.Text = Resources.Resources.ShowWarningNextTime;
                checkBoxParameters.Value = true;

                DialogResult dr = ApplicationAlert.Show(Resources.Resources.SortTagsWarning, Resources.Resources.ApplicationName, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, ref checkBoxParameters);

                if (dr != DialogResult.OK)
                {
                    return;
                }

                if (checkBoxParameters.Value == false)
                {
                    ApplicationSettings.Default.ShowTagSortMessage = false;
                    ApplicationSettings.Default.Save();
                }
            }

            TreeNode selectedNode = (TreeNode)TagTreeContextMenu.Tag;
            ImageTag selectedTag = (ImageTag)selectedNode.Tag;

            int scrollOffset = myPhotoIndexImageTagTreeView1.ScrollOffset;
            selectedNode.TreeView.BeginUpdate();

            IComparer currentSorter = selectedNode.TreeView.TreeViewNodeSorter;
            selectedNode.TreeView.TreeViewNodeSorter = new TagTreeNodeAlphaBeticalSorter(selectedNode);

            selectedNode.TreeView.Sort();

            int newOffset = 0;
            foreach (TreeNode node in selectedNode.Nodes)
            {
                IImageTag tag = node.Tag as IImageTag;
                tag.Offset = newOffset++;
                ImageTagCollection.Instance.SaveTag(tag);
            }

            selectedNode.TreeView.TreeViewNodeSorter = currentSorter;
            selectedNode.TreeView.Sort();

            myPhotoIndexImageTagTreeView1.SelectedNode = selectedNode;
            myPhotoIndexImageTagTreeView1.UpdateTreeNodesHeight();
            selectedNode.TreeView.EndUpdate();
            myPhotoIndexImageTagTreeView1.ScrollOffset = scrollOffset;
        }

        void SortByTagDatetoolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (ApplicationSettings.Default.ShowTagSortMessage == true)
            {
                CheckBoxParameters checkBoxParameters = new CheckBoxParameters();
                checkBoxParameters.Text = Resources.Resources.ShowWarningNextTime;
                checkBoxParameters.Value = true;

                DialogResult dr = ApplicationAlert.Show(Resources.Resources.SortTagsWarning, Resources.Resources.ApplicationName, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, ref checkBoxParameters);

                if (dr != DialogResult.OK)
                {
                    return;
                }

                if (checkBoxParameters.Value == false)
                {
                    ApplicationSettings.Default.ShowTagSortMessage = false;
                    ApplicationSettings.Default.Save();
                }
            }

            TreeNode selectedNode = (TreeNode)TagTreeContextMenu.Tag;
            ImageTag selectedTag = (ImageTag)selectedNode.Tag;

            int scrollOffset = myPhotoIndexImageTagTreeView1.ScrollOffset;
            selectedNode.TreeView.BeginUpdate();

            IComparer currentSorter = selectedNode.TreeView.TreeViewNodeSorter;
            selectedNode.TreeView.TreeViewNodeSorter = new TagTreeDateSorter(selectedNode);

            selectedNode.TreeView.Sort();

            int newOffset = 0;
            foreach (TreeNode node in selectedNode.Nodes)
            {
                IImageTag tag = node.Tag as IImageTag;
                tag.Offset = newOffset++;
                ImageTagCollection.Instance.SaveTag(tag);
            }

            selectedNode.TreeView.TreeViewNodeSorter = currentSorter;
            selectedNode.TreeView.Sort();

            myPhotoIndexImageTagTreeView1.SelectedNode = selectedNode;
            myPhotoIndexImageTagTreeView1.UpdateTreeNodesHeight();
            selectedNode.TreeView.EndUpdate();
            myPhotoIndexImageTagTreeView1.ScrollOffset = scrollOffset;
        }

        void cmProperties_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = (TreeNode)TagTreeContextMenu.Tag;
            ImageTag selectedTag = (ImageTag)selectedNode.Tag;

            bool needUpdate = false;
            TagEdit tef = new TagEdit(selectedTag, selectedNode);
            DialogResult dr = tef.ShowDialog(this);
            if (dr == DialogResult.OK)
            {
                selectedNode.Text = selectedTag.Name;

                if (tef.PositionChanged == false)
                {
                    ImageTagCollection.Instance.SaveTag(selectedTag);
                    ClearImageAddTagMenu();
                }
                else
                {
                    selectedNode.TreeView.BeginUpdate();
                    //reposition items
                    int newOffset = 0;
                    foreach (TreeNode node in selectedNode.Parent.Nodes)
                    {
                        IImageTag tag = node.Tag as IImageTag;
                        tag.Offset = newOffset++;
                        ImageTagCollection.Instance.SaveTag(tag);
                        ClearImageAddTagMenu();
                    }

                    needUpdate = true;
                }
            }
            else
            {
                if (tef.PositionChanged == true)
                {
                    needUpdate = true;
                }
            }

            if (needUpdate == true)
            {
                int scrollOffset = myPhotoIndexImageTagTreeView1.ScrollOffset;
                myPhotoIndexImageTagTreeView1.Sort();
                myPhotoIndexImageTagTreeView1.SelectedNode = selectedNode;
                myPhotoIndexImageTagTreeView1.UpdateTreeNodesHeight();
                selectedNode.TreeView.EndUpdate();
                myPhotoIndexImageTagTreeView1.ScrollOffset = scrollOffset;
            }
        }

        void cmRemoveTag_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = (TreeNode)TagTreeContextMenu.Tag;
            ImageTag selectedTag = (ImageTag)selectedNode.Tag;

            DialogResult result = ApplicationAlert.Show(Resources.Resources.DeleteTagAlert, Resources.Resources.DeleteTagAlertTitle, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
            if (result != DialogResult.OK)
            {
                return;
            }

            #region Remove tag from all of the relevant images
            QueryParameter[] parameters = new QueryParameter[] { new ImageTagQueryParameter(selectedTag.Id) };
            IImageCollection imageCollection = new QueryHelper(Storage.Instance.UnFiltered);
            QueryBuilder queryBuilder = new QueryBuilder(parameters, imageCollection, true);
            Dictionary<int, IImageData> queryResult = queryBuilder.RunQuery();

            List<int> imageList = new List<int>(queryResult.Keys);
            ReadOnlyCollection<int> roCollection = new ReadOnlyCollection<int>(imageList);
            Storage.Instance.AddRemoveImageTags(roCollection, new int[] { selectedTag.Id }, false);
            #endregion

            selectedNode.Remove();
            ImageTagCollection.Instance.RemoveTag(selectedTag);

            RefreshTagsPalette();
            ClearImageAddTagMenu();
        }

        private void ClearImageAddTagMenu()
        {
            addTagToolStripMenuItem.DropDownItems.Clear();
        }

        void cmAddTag_Click(object sender, EventArgs e)
        {
            TreeNode selectedNode = (TreeNode)TagTreeContextMenu.Tag;
            ImageTag selectedTag = (ImageTag)selectedNode.Tag;

            IImageTag newTag = ImageTagCollection.Instance.Create(selectedTag, Resources.Resources.TagTree_NewTag);

            TagEdit tef = new TagEdit(newTag, null);
            tef.Left = MousePosition.X;
            DialogResult dr = tef.ShowDialog(this);
            if (dr == DialogResult.OK)
            {
                ImageTagCollection.Instance.SaveTag(newTag);
                TreeNode childNode = selectedNode.Nodes.Add(newTag.Id.ToString(CultureInfo.InvariantCulture), newTag.Name);
                childNode.Tag = newTag;
                myPhotoIndexImageTagTreeView1.UpdateTreeNodesHeight();
                childNode.EnsureVisible();
                RefreshTagsPalette();
                ClearImageAddTagMenu();
            }
        }

        private void myPhotoIndexImageTagTreeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            TreeNode selectedNode = e.Node;
            if (e.Button == MouseButtons.Right)
            {
                TagTreeContextMenu.Items["cmAddTag"].Text = String.Format(Resources.Resources.TagTree_AddNewTag, selectedNode.Text);
                TagTreeContextMenu.Items["cmRemoveTag"].Text = String.Format(Resources.Resources.TagTree_RemoveTag, selectedNode.Text);

                TagTreeContextMenu.Items["cmProperties"].Text = String.Format(Resources.Resources.TagTree_EditTag, selectedNode.Text);
                TagTreeContextMenu.Tag = selectedNode;
                TagTreeContextMenu.Show(myPhotoIndexImageTagTreeView1, e.X, e.Y);
            }
        }

        void assignToSelectedImagesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AssignSelectedTagsToImages();
        }

        void AssignSelectedTagsToImages()
        {
            List<int> tagList = new List<int>();
            foreach (TreeNode node in myPhotoIndexImageTagTreeView1.SelectedNodes)
            {
                if (node.Parent != null)
                {
                    int tagId = Convert.ToInt32(node.Name, CultureInfo.InvariantCulture);
                    tagList.Add(tagId);
                }
            }

            ReadOnlyCollection<int> selectedCollection = photoThumbViewer1.SelectedImages;
            photoThumbViewer1.FlashThumbnailTagIcons(new List<int>(selectedCollection).ToArray());
            Storage.Instance.AddRemoveImageTags(selectedCollection, tagList.ToArray(), true);

            foreach (int tagId in tagList)
            {
                IImageTag tag = myPhotoIndexImageTagTreeView1.GetTag(tagId);
                if (tag.Thumbnail == null)
                {
                    tag.Thumbnail = new Bitmap(Storage.Instance[selectedCollection[0]].Thumbnail);
                    ImageTagCollection.Instance.SaveTag(tag);
                }
            }
        }

        private void fullScreenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int selectedImage = -1;
            if (this.photoThumbViewer1.SelectedImages.Count > 0)
            {
                selectedImage = this.photoThumbViewer1.SelectedImages[this.photoThumbViewer1.SelectedImages.Count - 1];
            }

            FullScreenForm fsf = new FullScreenForm(selectedImage);
            SelectedImageCollection selectedImageCollection = null;

            List<int> list = new List<int>();
            foreach (ImageData imageData in photoThumbViewer1.ImageList)
            {
                list.Add(imageData.Id);
            }

            selectedImageCollection = new SelectedImageCollection(new ReadOnlyCollection<int>(list), photoThumbViewer1.ImageList);

            fsf.ImageList = selectedImageCollection;
            fsf.ShowDialog(this);

            foreach (int imageId in fsf.SelectedList)
            {
                m_selectedImages.Add(imageId);
            }

            AdjustSelectedImagesPane();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutBox = new AboutBox1();
            aboutBox.ShowDialog(this);
        }

        private void rating_Stars_Click(object sender, EventArgs e)
        {
            ToolStripDropDownItem ddi = (ToolStripDropDownItem)sender;
            int numberOfStars = 0;
            switch (ddi.Name)
            {
                case "rating_5stars":
                    ++numberOfStars;
                    goto case "rating_4stars";
                case "rating_4stars":
                    ++numberOfStars;
                    goto case "rating_3stars";
                case "rating_3stars":
                    ++numberOfStars;
                    goto case "rating_2stars";
                case "rating_2stars":
                    ++numberOfStars;
                    goto case "rating_1stars";
                case "rating_1stars":
                    ++numberOfStars;
                    break;
                default:
                    break;
            }

            ReadOnlyCollection<int> selectedImages = (ReadOnlyCollection<int>)ddi.Owner.Tag;
            if (photoThumbViewer1.SelectedImages.Contains(selectedImages[0]) == true)
            {
                selectedImages = photoThumbViewer1.SelectedImages;
            }

            Storage.Instance.UpdateImageRating(selectedImages, numberOfStars);
        }

        private void applicationSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ApplicationSettingsForm appSettings = new ApplicationSettingsForm();
            appSettings.ShowDialog(this);
        }

        private void ShareImages(bool useSelectedPane)
        {
            bool showWarning = false;
            List<IImageData> fileList = new List<IImageData>();
            if (useSelectedPane == true)
            {
                foreach (IImageData imageData in SelectedThumbnailViewer.ImageList)
                {
                    if (ValidateEncryptedImage(imageData) == true &&
                        imageData.IsVideo == false)
                    {
                        fileList.Add(imageData);
                    }
                    else
                    {
                        showWarning = true;
                    }
                }
            }
            else
            {
                foreach (int imageId in photoThumbViewer1.SelectedImages)
                {
                    IImageData imageData = Storage.Instance[imageId];
                    if (ValidateEncryptedImage(imageData) == true &&
                        imageData.IsVideo == false)
                    {
                        fileList.Add(imageData);
                    }
                    else
                    {
                        showWarning = true;
                    }
                }
            }

            if (fileList.Count == 0)
            {
                return;
            }

            PluginSelectionForm psf = new PluginSelectionForm(typeof(ISharePlugin));
            if (psf.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            if (ApplicationSettings.Default.ShowShareSettingsForm)
            {
                SharePreferences sp = new SharePreferences();
                if (sp.ShowDialog() == DialogResult.Cancel)
                {
                    return;
                }
            }

            String defaultSharePlugin = ApplicationSettings.Default.DefaultMailPlugin;
            ISharePlugin mailer = null;
            foreach (ISharePlugin plugin in Manager.GetPlugins<ISharePlugin>())
            {
                if (String.Compare(defaultSharePlugin, plugin.GetType().FullName, true, CultureInfo.InvariantCulture) == 0)
                {
                    mailer = plugin;
                    break;
                }
            }

            if (mailer == null)
            {
                return;
            }

            Size imageSize = ApplicationSettings.Default.DefaultMailImageSize;

            mailer.Send(fileList.AsReadOnly(), imageSize);
        }

        private static bool ValidateEncryptedImage(IImageData imageData)
        {
            return !imageData.Encrypted;
        }

        private void EditImageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ToolStripDropDownItem ddi = (ToolStripDropDownItem)sender;
                Thumbnail thumbnail = ddi.Owner.Tag as Thumbnail;
                IImageData imageData = thumbnail.ImageData;
                String fileName = String.Format("\"{0}\"", imageData.FileName);

                String defaultApplication = ApplicationSettings.Default.DefaultImagesEditSoftware;
                if (String.IsNullOrEmpty(defaultApplication))
                {
                    ApplicationSettingsForm.ShowAndHighliteSettting(this, "DefaultImagesEditSoftware");
                    defaultApplication = ApplicationSettings.Default.DefaultImagesEditSoftware;
                }

                if (String.IsNullOrEmpty(defaultApplication) == false)
                {
                    bool createImageVersion = true;
                    if (ApplicationSettings.Default.ShowImageCreateVersionMessage == true)
                    {
                        CheckBoxParameters checkBox = new CheckBoxParameters();
                        checkBox.Value = true;
                        checkBox.Text = Resources.Resources.ImageVersionsAskMeNextTime;
                        DialogResult dr = ApplicationAlert.Show(Resources.Resources.CreateImageVersion, Resources.Resources.ApplicationName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, ref checkBox);
                        if (dr != DialogResult.Yes)
                        {
                            createImageVersion = false;
                        }

                        if (ApplicationSettings.Default.ShowImageCreateVersionMessage != checkBox.Value)
                        {
                            ApplicationSettings.Default.ShowImageCreateVersionMessage = checkBox.Value;
                            ApplicationSettings.Default.Save();
                        }
                    }

                    if (createImageVersion == true)
                    {
                        Storage.Instance.CreateNewVersion(imageData, DateTime.Now);
                        UpdateMenuItemsStatus();
                    }

                    Process process = Process.Start(ApplicationSettings.Default.DefaultImagesEditSoftware, fileName);
                }
            }
            catch (Exception ex)
            {
                Logger.Log(ex);
            }
        }

        private void GoToHomePageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start(Resources.Resources.WebSiteUrl);
        }

        private void GotoForumsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start(String.Format("{0}/Forums.aspx", Resources.Resources.WebSiteUrl));
        }

        private void onlineHelpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start(String.Format("{0}/Help.aspx", Resources.Resources.WebSiteUrl));
        }

        void SelectedThumbnailViewerContextMenu_ThumbnailMouseClickEvent(object sender, ThumbnailMouseEventArgs e)
        {
            if (e.MouseButton == MouseButtons.Right)
            {
                SelectedImagesContextMenu.Tag = SelectedThumbnailViewer;
                SelectedImagesContextMenu.Show(SelectedThumbnailViewer, e.X, e.Y);
            }
        }

        void SelectedThumbnailViewer_DragEnter(object sender, DragEventArgs e)
        {
            Win32Interop.ImageDragHelper.ImageList_DragEnter(this.SelectedThumbnailViewer.Handle, e.X - this.SelectedThumbnailViewer.Left, e.Y - this.SelectedThumbnailViewer.Top);
        }

        void SelectedThumbnailViewer_DragLeave(object sender, EventArgs e)
        {
            Win32Interop.ImageDragHelper.ImageList_DragLeave(this.SelectedThumbnailViewer.Handle);
        }

        void SelectedThumbnailViewer_DragOver(object sender, DragEventArgs e)
        {
            // Compute drag position and move image
            Point point = SelectedThumbnailViewer.PointToClient(new Point(e.X, e.Y));
            Win32Interop.ImageDragHelper.ImageList_DragMove(point.X, point.Y);

            Thumbnail tn = (Thumbnail)e.Data.GetData(typeof(Thumbnail));
            TreeNode treeNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
            if (tn != null &&
                tn.ImageData is ImageData)
            {
                e.Effect = DragDropEffects.Link;
            }
            else
                if (tn != null &&
                tn.ImageData is TagsImageData &&
                m_selectedImages.Count > 0)
                {
                    e.Effect = DragDropEffects.Link;
                }
                else
                    if (m_selectedImages.Count > 0 &&
                        treeNode != null &&
                        treeNode.Parent != null)
                    {
                        e.Effect = DragDropEffects.Link;
                    }
                    else
                    {
                        e.Effect = DragDropEffects.None;
                    }
        }

        void SelectedThumbnailViewer_DragDrop(object sender, DragEventArgs e)
        {
            Thumbnail tn = (Thumbnail)e.Data.GetData(typeof(Thumbnail));
            if (tn != null &&
                tn.ImageData is ImageData)
            {
                if (photoThumbViewer1.IsSelected(tn.ImageId) == true)
                {
                    m_selectedImages.AddRange(photoThumbViewer1.SelectedImages);
                }
                else
                {
                    m_selectedImages.Add(tn.ImageId);
                }

                AdjustSelectedImagesPane();
                return;
            }

            if (m_selectedImages.Count == 0)
            {
                return;
            }

            TreeNode selectedtagNode = (TreeNode)e.Data.GetData(typeof(TreeNode));

            List<int> tagList = new List<int>();
            if (tn != null &&
                tn.ImageData is TagsImageData)
            {
                if (tn.Parent.SelectedImages.Contains(tn.ImageData.Id) == true)
                {
                    tagList.AddRange(tn.Parent.SelectedImages);
                }
                else
                {
                    tagList.Add(tn.ImageData.Id);
                }
            }
            else
                if (selectedtagNode != null)
                {
                    int tagId = Convert.ToInt32(selectedtagNode.Name, CultureInfo.InvariantCulture);
                    tagList.Add(tagId);
                }

            if (tagList.Count == 0)
            {
                return;
            }

            List<int> selectedCollection = new List<int>();
            foreach (ImageData imageData in m_selectedImages)
            {
                selectedCollection.Add(imageData.Id);
            }

            Storage.Instance.AddRemoveImageTags(selectedCollection.AsReadOnly(), tagList.ToArray(), true);

            foreach (int tagId in tagList)
            {
                IImageTag tag = myPhotoIndexImageTagTreeView1.GetTag(tagId);
                if (tag.Thumbnail == null)
                {
                    tag.Thumbnail = new Bitmap(m_selectedImages[0].Thumbnail);
                    ImageTagCollection.Instance.SaveTag(tag);
                }
            }
        }

        private void ClearSelectedPane()
        {
            m_selectedImages.Clear();
            AdjustSelectedImagesPane();
        }

        private void menuStrip1_Paint(object sender, PaintEventArgs e)
        {
            Rectangle drawRect = e.ClipRectangle;
            if (drawRect == Rectangle.Empty)
            {
                return;
            }

            Color firstColor = Color.FromArgb(225, 238, 255);
            using (Brush brush = new SolidBrush(firstColor))
            {
                e.Graphics.FillRectangle(brush, drawRect);
            }
        }

        private void statusStrip1_Paint(object sender, PaintEventArgs e)
        {
            Rectangle drawRect = statusStrip1.ClientRectangle;
            if (drawRect == Rectangle.Empty)
            {
                return;
            }

            Graphics g = e.Graphics;
            g.InterpolationMode = InterpolationMode.NearestNeighbor;

            Color borderColor = Color.White;
            Point start = new Point(0, 0);
            Point end = new Point(drawRect.Width, 0);
            using (Pen borderPen = new Pen(borderColor))
            {
                g.DrawLine(borderPen, start, end);
            }

            Color firstColor = Color.FromArgb(225, 238, 255);
            Color secondColor = Color.FromArgb(140, 164, 193);

            using (Brush brush = new LinearGradientBrush(drawRect,
                                firstColor, secondColor, LinearGradientMode.Vertical))
            {
                g.FillRectangle(brush, drawRect);
            }
        }

        private void ClearCachedPasswordsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            IEncryptedFormatProvider provider = ImageFormatProviders.Default["mei"] as IEncryptedFormatProvider;
            if (provider == null)
            {
                return;
            }

            provider.ClearKeys();
            Storage.Instance.RefreshCache();
            photoThumbViewer1.Refresh();

        }

        private void advancedQueryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ComplexSearchForm aqf = new ComplexSearchForm();
            aqf.StartPosition = FormStartPosition.CenterParent;
            aqf.Show(this);
        }

        private void Edit_Delete_MenuItem_Click(object sender, EventArgs e)
        {
            if (photoThumbViewer1.Focused == false)
            {
                if (toolStripSearchBox.Focused == true)
                {
                    toolStripSearchBox.InnerControl.SelectedText = string.Empty;
                    return;
                }

                if (myPhotoIndexImageTagTreeView1.Focused == true)
                {
                    return;
                }
            }

            DeletetoolStripMenuItem_Click(sender, e);
        }

        void photoThumbViewer1_KeyPress(object sender, KeyPressEventArgs e)
        {

        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            bool handled = ApplicationSettings.Default.KeyboardMappings.HandleShortcut(keyData);
            if (handled == true)
            {
                return true;
            }

            if (photoThumbViewer1.Focused == false)
            {
                return base.ProcessCmdKey(ref msg, keyData);
            }

            if ((keyData & Keys.Oemplus) == Keys.Oemplus &&
                (keyData & Keys.Control) == Keys.Control)
            {
                ThumbnailZoomIn();
                return true;
            }

            if ((keyData & Keys.OemMinus) == Keys.OemMinus &&
                (keyData & Keys.Control) == Keys.Control)
            {
                ThumbnailZoomOut();
                return true;
            }

            switch (keyData)
            {
                case Keys.Return:
                    if (MyPhotoIndexTrackBar1.Value > 1)
                    {
                        toolStripLargest_Click();
                    }
                    break;

                case Keys.Back:
                    if (MyPhotoIndexTrackBar1.Value == 1)
                    {
                        toolStripGoBack_Click();
                    }
                    break;

                case (Keys)107://num+
                    ThumbnailZoomIn();
                    break;

                case (Keys)109://num-
                    ThumbnailZoomOut();
                    break;
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }
    }
}